[apps] Operations in double when precision required

Change-Id: I7168a861a76178f0bf81841e9378f7399f67914a
This commit is contained in:
Émilie Feral
2017-08-04 18:24:09 +02:00
parent 82e212e771
commit f0a776a670
82 changed files with 494 additions and 463 deletions

View File

@@ -1,11 +1,11 @@
#ifndef CALCULATION_APP_H
#define CALCULATION_APP_H
#include "edit_expression_controller.h"
#include "local_context.h"
#include "history_controller.h"
#include "../shared/text_field_delegate_app.h"
#include "calculation_store.h"
#include "edit_expression_controller.h"
#include "history_controller.h"
#include "local_context.h"
#include "../shared/text_field_delegate_app.h"
#include <escher.h>
namespace Calculation {

View File

@@ -43,29 +43,29 @@ void GraphController::reloadBannerView() {
buffer[0] = f->name()[0];
buffer[1] = '\'';
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
float y = f->approximateDerivative(m_cursor->x(), myApp->localContext());
double y = f->approximateDerivative(m_cursor->x(), myApp->localContext());
Complex<double>::convertFloatToText(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
m_bannerView.setLegendAtIndex(buffer, 2);
}
bool GraphController::moveCursorHorizontally(int direction) {
float xCursorPosition = m_cursor->x();
float x = direction > 0 ? xCursorPosition + m_graphRange->xGridUnit()/k_numberOfCursorStepsInGradUnit :
double xCursorPosition = m_cursor->x();
double x = direction > 0 ? xCursorPosition + m_graphRange->xGridUnit()/k_numberOfCursorStepsInGradUnit :
xCursorPosition - m_graphRange->xGridUnit()/k_numberOfCursorStepsInGradUnit;
CartesianFunction * f = m_functionStore->activeFunctionAtIndex(m_indexFunctionSelectedByCursor);
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
float y = f->evaluateAtAbscissa(x, myApp->localContext());
double y = f->evaluateAtAbscissa(x, myApp->localContext());
m_cursor->moveTo(x, y);
m_graphRange->panToMakePointVisible(x, y, k_cursorTopMarginRatio, k_cursorRightMarginRatio, k_cursorBottomMarginRatio, k_cursorLeftMarginRatio);
return true;
}
void GraphController::initCursorParameters() {
float x = (interactiveCurveViewRange()->xMin()+interactiveCurveViewRange()->xMax())/2.0f;
double x = (interactiveCurveViewRange()->xMin()+interactiveCurveViewRange()->xMax())/2.0f;
m_indexFunctionSelectedByCursor = 0;
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
int functionIndex = 0;
float y = 0;
double y = 0;
do {
CartesianFunction * firstFunction = functionStore()->activeFunctionAtIndex(functionIndex++);
y = firstFunction->evaluateAtAbscissa(x, myApp->localContext());

View File

@@ -140,7 +140,7 @@ FunctionParameterController * ValuesController::functionParameterController() {
return &m_functionParameterController;
}
float ValuesController::evaluationOfAbscissaAtColumn(float abscissa, int columnIndex) {
double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) {
CartesianFunction * function = functionAtColumn(columnIndex);
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
if (isDerivativeColumn(columnIndex)) {

View File

@@ -24,7 +24,7 @@ private:
void configureDerivativeFunction();
int maxNumberOfCells() override;
int maxNumberOfFunctions() override;
float evaluationOfAbscissaAtColumn(float abscissa, int columnIndex) override;
double evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) override;
constexpr static int k_maxNumberOfCells = 50;
constexpr static int k_maxNumberOfFunctions = 5;
FunctionTitleCell * m_functionTitleCells[k_maxNumberOfFunctions];

View File

@@ -31,7 +31,7 @@ UpdateController::ContentView::ContentView() :
m_messageTextView2(KDText::FontSize::Small, I18n::Message::UpdateMessage2, 0.5f, 0.5f),
m_messageTextView3(KDText::FontSize::Small, I18n::Message::UpdateMessage3, 0.5f, 0.5f),
m_messageTextView4(KDText::FontSize::Small, I18n::Message::UpdateMessage4, 0.5f, 0.5f, Palette::YellowDark),
m_skipView(KDText::FontSize::Small, I18n::Message::Skip, 1.0f, 0.5),
m_skipView(KDText::FontSize::Small, I18n::Message::Skip, 1.0f, 0.5f),
m_okView()
{
}

View File

@@ -18,11 +18,11 @@ int Calculation::numberOfEditableParameters() {
return numberOfParameters();
}
float Calculation::lowerBound() {
double Calculation::lowerBound() {
return -INFINITY;
}
float Calculation::upperBound() {
double Calculation::upperBound() {
return INFINITY;
}

View File

@@ -20,15 +20,15 @@ public:
virtual int numberOfParameters() = 0;
virtual int numberOfEditableParameters();
virtual I18n::Message legendForParameterAtIndex(int index) = 0;
virtual void setParameterAtIndex(float f, int index) = 0;
virtual float parameterAtIndex(int index) = 0;
virtual float lowerBound();
virtual float upperBound();
virtual void setParameterAtIndex(double f, int index) = 0;
virtual double parameterAtIndex(int index) = 0;
virtual double lowerBound();
virtual double upperBound();
protected:
/* Parameters in probability application are rounded to 3 decimals. This is
* due to the limited precision of some calculation (e. g. standard normal
* cumulative distributive function or inverse). */
constexpr static float k_precision = 0.001f;
constexpr static double k_precision = 0.001;
virtual void compute(int indexKnownElement) = 0;
Law * m_law;
};

View File

@@ -7,8 +7,8 @@ namespace Probability {
DiscreteCalculation::DiscreteCalculation() :
Calculation(),
m_abscissa(0.0f),
m_result(0.0f)
m_abscissa(0.0),
m_result(0.0)
{
compute(0);
}
@@ -33,15 +33,15 @@ I18n::Message DiscreteCalculation::legendForParameterAtIndex(int index) {
return I18n::Message::LeftIntegralSecondLegend;
}
void DiscreteCalculation::setParameterAtIndex(float f, int index) {
void DiscreteCalculation::setParameterAtIndex(double f, int index) {
assert(index == 0);
float rf = std::round(f);
double rf = std::round(f);
m_abscissa = rf;
compute(index);
}
float DiscreteCalculation::parameterAtIndex(int index) {
double DiscreteCalculation::parameterAtIndex(int index) {
assert(index >= 0 && index < 2);
if (index == 0) {
return m_abscissa;
@@ -49,11 +49,11 @@ float DiscreteCalculation::parameterAtIndex(int index) {
return m_result;
}
float DiscreteCalculation::lowerBound() {
double DiscreteCalculation::lowerBound() {
return m_abscissa;
}
float DiscreteCalculation::upperBound() {
double DiscreteCalculation::upperBound() {
return m_abscissa;
}
@@ -61,7 +61,7 @@ void DiscreteCalculation::compute(int indexKnownElement) {
if (m_law == nullptr) {
return;
}
m_result = m_law->evaluateAtAbscissa(m_abscissa);
m_result = m_law->evaluateAtDiscreteAbscissa(m_abscissa);
/* Results in probability application are rounder to 3 decimals */
m_result = std::round(m_result/k_precision)*k_precision;
}

View File

@@ -12,14 +12,14 @@ public:
int numberOfParameters() override;
int numberOfEditableParameters() override;
I18n::Message legendForParameterAtIndex(int index) override;
void setParameterAtIndex(float f, int index) override;
float parameterAtIndex(int index) override;
float lowerBound() override;
float upperBound() override;
void setParameterAtIndex(double f, int index) override;
double parameterAtIndex(int index) override;
double lowerBound() override;
double upperBound() override;
private:
void compute(int indexKnownElement) override;
float m_abscissa;
float m_result;
double m_abscissa;
double m_result;
};
}

View File

@@ -8,9 +8,9 @@ namespace Probability {
FiniteIntegralCalculation::FiniteIntegralCalculation() :
Calculation(),
m_lowerBound(0.0f),
m_upperBound(1.0f),
m_result(0.0f)
m_lowerBound(0.0),
m_upperBound(1.0),
m_result(0.0)
{
compute(0);
}
@@ -41,9 +41,9 @@ I18n::Message FiniteIntegralCalculation::legendForParameterAtIndex(int index) {
return I18n::Message::LeftIntegralSecondLegend;
}
void FiniteIntegralCalculation::setParameterAtIndex(float f, int index) {
void FiniteIntegralCalculation::setParameterAtIndex(double f, int index) {
assert(index >= 0 && index < 3);
float rf = std::round(f/k_precision)*k_precision;
double rf = std::round(f/k_precision)*k_precision;
if (index == 0) {
m_lowerBound = rf;
}
@@ -57,7 +57,7 @@ void FiniteIntegralCalculation::setParameterAtIndex(float f, int index) {
}
float FiniteIntegralCalculation::parameterAtIndex(int index) {
double FiniteIntegralCalculation::parameterAtIndex(int index) {
assert(index >= 0 && index < 3);
if (index == 0) {
return m_lowerBound;
@@ -68,11 +68,11 @@ float FiniteIntegralCalculation::parameterAtIndex(int index) {
return m_result;
}
float FiniteIntegralCalculation::lowerBound() {
double FiniteIntegralCalculation::lowerBound() {
return m_lowerBound;
}
float FiniteIntegralCalculation::upperBound() {
double FiniteIntegralCalculation::upperBound() {
return m_upperBound;
}
@@ -82,9 +82,9 @@ void FiniteIntegralCalculation::compute(int indexKnownElement) {
}
if (indexKnownElement == 2) {
assert(m_law->type() == Law::Type::Normal);
float p = (1.0f+m_result)/2.0f;
float a = ((NormalLaw *)m_law)->cumulativeDistributiveInverseForProbability(&p);
m_lowerBound = std::round((2.0f*m_law->parameterValueAtIndex(0)-a)/k_precision)*k_precision;
double p = (1.0+m_result)/2.0;
double a = ((NormalLaw *)m_law)->cumulativeDistributiveInverseForProbability(&p);
m_lowerBound = std::round((2.0*m_law->parameterValueAtIndex(0)-a)/k_precision)*k_precision;
m_upperBound = std::round(a/k_precision)*k_precision;
}
m_result = m_law->finiteIntegralBetweenAbscissas(m_lowerBound, m_upperBound);

View File

@@ -12,15 +12,15 @@ public:
int numberOfParameters() override;
int numberOfEditableParameters() override;
I18n::Message legendForParameterAtIndex(int index) override;
void setParameterAtIndex(float f, int index) override;
float parameterAtIndex(int index) override;
float lowerBound() override;
float upperBound() override;
void setParameterAtIndex(double f, int index) override;
double parameterAtIndex(int index) override;
double lowerBound() override;
double upperBound() override;
private:
void compute(int indexKnownElement) override;
float m_lowerBound;
float m_upperBound;
float m_result;
double m_lowerBound;
double m_upperBound;
double m_result;
};
}

View File

@@ -7,8 +7,8 @@ namespace Probability {
LeftIntegralCalculation::LeftIntegralCalculation() :
Calculation(),
m_upperBound(0.0f),
m_result(0.0f)
m_upperBound(0.0),
m_result(0.0)
{
compute(0);
}
@@ -29,9 +29,9 @@ I18n::Message LeftIntegralCalculation::legendForParameterAtIndex(int index) {
return I18n::Message::LeftIntegralSecondLegend;
}
void LeftIntegralCalculation::setParameterAtIndex(float f, int index) {
void LeftIntegralCalculation::setParameterAtIndex(double f, int index) {
assert(index >= 0 && index < 2);
float rf = std::round(f/k_precision)*k_precision;
double rf = std::round(f/k_precision)*k_precision;
if (index == 0) {
m_upperBound = rf;
}
@@ -41,7 +41,7 @@ void LeftIntegralCalculation::setParameterAtIndex(float f, int index) {
compute(index);
}
float LeftIntegralCalculation::parameterAtIndex(int index) {
double LeftIntegralCalculation::parameterAtIndex(int index) {
assert(index >= 0 && index < 2);
if (index == 0) {
return m_upperBound;
@@ -49,7 +49,7 @@ float LeftIntegralCalculation::parameterAtIndex(int index) {
return m_result;
}
float LeftIntegralCalculation::upperBound() {
double LeftIntegralCalculation::upperBound() {
return m_upperBound;
}

View File

@@ -11,13 +11,13 @@ public:
Type type() override;
int numberOfParameters() override;
I18n::Message legendForParameterAtIndex(int index) override;
void setParameterAtIndex(float f, int index) override;
float parameterAtIndex(int index) override;
float upperBound() override;
void setParameterAtIndex(double f, int index) override;
double parameterAtIndex(int index) override;
double upperBound() override;
private:
void compute(int indexKnownElement) override;
float m_upperBound;
float m_result;
double m_upperBound;
double m_result;
};
}

View File

@@ -7,8 +7,8 @@ namespace Probability {
RightIntegralCalculation::RightIntegralCalculation() :
Calculation(),
m_lowerBound(0.0f),
m_result(0.0f)
m_lowerBound(0.0),
m_result(0.0)
{
compute(0);
}
@@ -29,9 +29,9 @@ I18n::Message RightIntegralCalculation::legendForParameterAtIndex(int index) {
return I18n::Message::RightIntegralSecondLegend;
}
void RightIntegralCalculation::setParameterAtIndex(float f, int index) {
void RightIntegralCalculation::setParameterAtIndex(double f, int index) {
assert(index >= 0 && index < 2);
float rf = std::round(f/k_precision)*k_precision;
double rf = std::round(f/k_precision)*k_precision;
if (index == 0) {
m_lowerBound = rf;
}
@@ -41,7 +41,7 @@ void RightIntegralCalculation::setParameterAtIndex(float f, int index) {
compute(index);
}
float RightIntegralCalculation::parameterAtIndex(int index) {
double RightIntegralCalculation::parameterAtIndex(int index) {
assert(index >= 0 && index < 2);
if (index == 0) {
return m_lowerBound;
@@ -49,7 +49,7 @@ float RightIntegralCalculation::parameterAtIndex(int index) {
return m_result;
}
float RightIntegralCalculation::lowerBound() {
double RightIntegralCalculation::lowerBound() {
return m_lowerBound;
}

View File

@@ -11,13 +11,13 @@ public:
Type type() override;
int numberOfParameters() override;
I18n::Message legendForParameterAtIndex(int index) override;
void setParameterAtIndex(float f, int index) override;
float parameterAtIndex(int index) override;
float lowerBound() override;
void setParameterAtIndex(double f, int index) override;
double parameterAtIndex(int index) override;
double lowerBound() override;
private:
void compute(int indexKnownElement) override;
float m_lowerBound;
float m_result;
double m_lowerBound;
double m_result;
};
}

View File

@@ -224,11 +224,11 @@ bool CalculationController::textFieldDidFinishEditing(TextField * textField, con
return false;
}
if (m_calculation->type() != Calculation::Type::FiniteIntegral && m_highlightedSubviewIndex == 2) {
if (floatBody < 0.0f) {
floatBody = 0.0f;
if (floatBody < 0.0) {
floatBody = 0.0;
}
if (floatBody > 1.0f) {
floatBody = 1.0f;
if (floatBody > 1.0) {
floatBody = 1.0;
}
}
if (!m_law->isContinuous() && (m_highlightedSubviewIndex == 1 || m_calculation->type() == Calculation::Type::FiniteIntegral)) {

View File

@@ -5,7 +5,7 @@
namespace Probability {
BinomialLaw::BinomialLaw() :
TwoParameterLaw(20.0f, 0.5f)
TwoParameterLaw(20.0, 0.5)
{
}
@@ -67,68 +67,72 @@ float BinomialLaw::yMax() {
return result*(1.0f+ k_displayTopMarginRatio);
}
float BinomialLaw::evaluateAtAbscissa(float x) const {
if (m_parameter1 == 0.0f) {
if (m_parameter2 == 0.0f || m_parameter2 == 1.0f) {
return NAN;
}
if ((int)x == 0) {
return 1.0f;
}
return 0.0f;
}
if (m_parameter2 == 1.0f) {
if ((int)x == m_parameter1) {
return 1.0f;
}
return 0.0f;
}
if (m_parameter2 == 0.0f) {
if ((int)x == 0) {
return 1.0f;
}
return 0.0f;
}
if (x > m_parameter1) {
return 0.0f;
}
float lResult = std::lgamma(m_parameter1+1) - std::lgamma(floorf(x)+1.0f) - std::lgamma(m_parameter1 - floorf(x)+1.0f)+
(int)x*std::log(m_parameter2) + (m_parameter1-(int)x)*std::log(1-m_parameter2);
return std::exp(lResult);
}
bool BinomialLaw::authorizedValueAtIndex(float x, int index) const {
bool BinomialLaw::authorizedValueAtIndex(double x, int index) const {
if (index == 0) {
if (x != (int)x || x < 0.0f || x > 999.0f) {
if (x != (int)x || x < 0.0 || x > 999.0) {
return false;
}
return true;
}
if (x < 0.0f || x > 1.0f) {
if (x < 0.0 || x > 1.0) {
return false;
}
return true;
}
float BinomialLaw::cumulativeDistributiveInverseForProbability(float * probability) {
if (m_parameter1 == 0.0f && (m_parameter2 == 0.0f || m_parameter2 == 1.0f)) {
double BinomialLaw::cumulativeDistributiveInverseForProbability(double * probability) {
if (m_parameter1 == 0.0 && (m_parameter2 == 0.0 || m_parameter2 == 1.0)) {
return NAN;
}
if (*probability >= 1.0f) {
if (*probability >= 1.0) {
return m_parameter1;
}
return Law::cumulativeDistributiveInverseForProbability(probability);
}
float BinomialLaw::rightIntegralInverseForProbability(float * probability) {
if (m_parameter1 == 0.0f && (m_parameter2 == 0.0f || m_parameter2 == 1.0f)) {
double BinomialLaw::rightIntegralInverseForProbability(double * probability) {
if (m_parameter1 == 0.0 && (m_parameter2 == 0.0 || m_parameter2 == 1.0)) {
return NAN;
}
if (*probability <= 0.0f) {
if (*probability <= 0.0) {
return m_parameter1;
}
return Law::rightIntegralInverseForProbability(probability);
}
template<typename T>
T BinomialLaw::templatedEvaluateAtAbscissa(T x) const {
if (m_parameter1 == 0) {
if (m_parameter2 == 0 || m_parameter2 == 1) {
return NAN;
}
if (floor(x) == 0) {
return 1;
}
return 0;
}
if (m_parameter2 == 1) {
if (floor(x) == m_parameter1) {
return 1;
}
return 0;
}
if (m_parameter2 == 0) {
if (floor(x) == 0) {
return 1;
}
return 0;
}
if (x > m_parameter1) {
return 0;
}
T lResult = std::lgamma(m_parameter1+1) - std::lgamma(std::floor(x)+1) - std::lgamma((T)m_parameter1 - std::floor(x)+1)+
std::floor(x)*std::log(m_parameter2) + (m_parameter1-std::floor(x))*std::log(1-m_parameter2);
return std::exp(lResult);
}
}
template float Probability::BinomialLaw::templatedEvaluateAtAbscissa(float x) const;
template double Probability::BinomialLaw::templatedEvaluateAtAbscissa(double x) const;

View File

@@ -17,10 +17,17 @@ public:
float yMax() override;
I18n::Message parameterNameAtIndex(int index) override;
I18n::Message parameterDefinitionAtIndex(int index) override;
float evaluateAtAbscissa(float x) const override;
bool authorizedValueAtIndex(float x, int index) const override;
float cumulativeDistributiveInverseForProbability(float * probability) override;
float rightIntegralInverseForProbability(float * probability) override;
float evaluateAtAbscissa(float x) const override {
return templatedEvaluateAtAbscissa(x);
}
bool authorizedValueAtIndex(double x, int index) const override;
double cumulativeDistributiveInverseForProbability(double * probability) override;
double rightIntegralInverseForProbability(double * probability) override;
protected:
double evaluateAtDiscreteAbscissa(int k) const override {
return templatedEvaluateAtAbscissa((double)k);
}
template<typename T> T templatedEvaluateAtAbscissa(T x) const;
};
}

View File

@@ -69,25 +69,25 @@ float ExponentialLaw::evaluateAtAbscissa(float x) const {
return m_parameter1*std::exp(-m_parameter1*x);
}
bool ExponentialLaw::authorizedValueAtIndex(float x, int index) const {
if (x <= 0.0f || x > 7500.0f) {
bool ExponentialLaw::authorizedValueAtIndex(double x, int index) const {
if (x <= 0.0 || x > 7500.0) {
return false;
}
return true;
}
float ExponentialLaw::cumulativeDistributiveFunctionAtAbscissa(float x) const {
return 1.0f - std::exp(-m_parameter1*x);
double ExponentialLaw::cumulativeDistributiveFunctionAtAbscissa(double x) const {
return 1.0 - std::exp((double)(-m_parameter1*x));
}
float ExponentialLaw::cumulativeDistributiveInverseForProbability(float * probability) {
if (*probability >= 1.0f) {
double ExponentialLaw::cumulativeDistributiveInverseForProbability(double * probability) {
if (*probability >= 1.0) {
return INFINITY;
}
if (*probability <= 0.0f) {
return 0.0f;
if (*probability <= 0.0) {
return 0.0;
}
return -std::log(1.0f - *probability)/m_parameter1;
return -std::log(1.0 - *probability)/(double)m_parameter1;
}
}

View File

@@ -18,9 +18,9 @@ public:
I18n::Message parameterNameAtIndex(int index) override;
I18n::Message parameterDefinitionAtIndex(int index) override;
float evaluateAtAbscissa(float x) const override;
bool authorizedValueAtIndex(float x, int index) const override;
float cumulativeDistributiveFunctionAtAbscissa(float x) const override;
float cumulativeDistributiveInverseForProbability(float * probability) override;
bool authorizedValueAtIndex(double x, int index) const override;
double cumulativeDistributiveFunctionAtAbscissa(double x) const override;
double cumulativeDistributiveInverseForProbability(double * probability) override;
};
}

View File

@@ -8,16 +8,17 @@ Law::Law() :
Shared::CurveViewRange()
{
}
float Law::xGridUnit() {
return computeGridUnit(Axis::X, xMin(), xMax());
}
float Law::cumulativeDistributiveFunctionAtAbscissa(float x) const {
double Law::cumulativeDistributiveFunctionAtAbscissa(double x) const {
if (!isContinuous()) {
int end = std::round(x);
float result = 0.0f;
double result = 0.0;
for (int k = 0; k <=end; k++) {
result += evaluateAtAbscissa(k);
result += evaluateAtDiscreteAbscissa(k);
/* Avoid too long loop */
if (result > k_maxProbability || k > k_maxNumberOfOperations) {
break;
@@ -25,28 +26,28 @@ float Law::cumulativeDistributiveFunctionAtAbscissa(float x) const {
}
return result;
}
return 0.0f;
return 0.0;
}
float Law::rightIntegralFromAbscissa(float x) const {
double Law::rightIntegralFromAbscissa(double x) const {
if (isContinuous()) {
return 1.0f - cumulativeDistributiveFunctionAtAbscissa(x);
return 1.0 - cumulativeDistributiveFunctionAtAbscissa(x);
}
return 1.0f - cumulativeDistributiveFunctionAtAbscissa(x-1.0f);
return 1.0 - cumulativeDistributiveFunctionAtAbscissa(x-1.0);
}
float Law::finiteIntegralBetweenAbscissas(float a, float b) const {
double Law::finiteIntegralBetweenAbscissas(double a, double b) const {
if (b < a) {
return 0.0f;
return 0.0;
}
if (isContinuous()) {
return cumulativeDistributiveFunctionAtAbscissa(b) - cumulativeDistributiveFunctionAtAbscissa(a);
}
int start = std::round(a);
int end = std::round(b);
float result = 0.0f;
double result = 0.0;
for (int k = start; k <=end; k++) {
result += evaluateAtAbscissa(k);
result += evaluateAtDiscreteAbscissa(k);
/* Avoid too long loop */
if (result > k_maxProbability || k-start > k_maxNumberOfOperations) {
break;
@@ -55,57 +56,61 @@ float Law::finiteIntegralBetweenAbscissas(float a, float b) const {
return result;
}
float Law::cumulativeDistributiveInverseForProbability(float * probability) {
if (*probability >= 1.0f) {
double Law::cumulativeDistributiveInverseForProbability(double * probability) {
if (*probability >= 1.0) {
return INFINITY;
}
if (isContinuous()) {
return 0.0f;
return 0.0;
}
if (*probability <= 0.0f) {
return 0.0f;
if (*probability <= 0.0) {
return 0.0;
}
float p = 0.0f;
double p = 0.0;
int k = 0;
while (p < *probability && k < k_maxNumberOfOperations) {
p += evaluateAtAbscissa(k++);
p += evaluateAtDiscreteAbscissa(k++);
}
if (k == k_maxNumberOfOperations) {
*probability = 1.0f;
*probability = 1.0;
return INFINITY;
}
*probability = p;
if (isnan(*probability)) {
return NAN;
}
return k-1;
return k-1.0f;
}
float Law::rightIntegralInverseForProbability(float * probability) {
double Law::rightIntegralInverseForProbability(double * probability) {
if (isContinuous()) {
float f = 1.0f - *probability;
double f = 1.0 - *probability;
return cumulativeDistributiveInverseForProbability(&f);
}
if (*probability >= 1.0f) {
return 0.0f;
if (*probability >= 1.0) {
return 0.0;
}
if (*probability <= 0.0f) {
if (*probability <= 0.0) {
return INFINITY;
}
float p = 0.0f;
double p = 0.0;
int k = 0;
while (p < 1.0f - *probability && k < k_maxNumberOfOperations) {
p += evaluateAtAbscissa(k++);
while (p < 1.0 - *probability && k < k_maxNumberOfOperations) {
p += evaluateAtDiscreteAbscissa(k++);
}
if (k == k_maxNumberOfOperations) {
*probability = 1.0f;
*probability = 1.0;
return INFINITY;
}
*probability = 1.0f - (p - evaluateAtAbscissa(k-1));
*probability = 1.0 - (p - evaluateAtDiscreteAbscissa(k-1));
if (isnan(*probability)) {
return NAN;
}
return k-1;
return k-1.0;
}
double Law::evaluateAtDiscreteAbscissa(int k) const {
return 0.0;
}
}

View File

@@ -29,15 +29,16 @@ public:
virtual I18n::Message parameterDefinitionAtIndex(int index) = 0;
virtual void setParameterAtIndex(float f, int index) = 0;
virtual float evaluateAtAbscissa(float x) const = 0;
virtual bool authorizedValueAtIndex(float x, int index) const = 0;
virtual float cumulativeDistributiveFunctionAtAbscissa(float x) const;
float rightIntegralFromAbscissa(float x) const;
float finiteIntegralBetweenAbscissas(float a, float b) const;
virtual float cumulativeDistributiveInverseForProbability(float * probability);
virtual float rightIntegralInverseForProbability(float * probability);
virtual bool authorizedValueAtIndex(double x, int index) const = 0;
virtual double cumulativeDistributiveFunctionAtAbscissa(double x) const;
double rightIntegralFromAbscissa(double x) const;
double finiteIntegralBetweenAbscissas(double a, double b) const;
virtual double cumulativeDistributiveInverseForProbability(double * probability);
virtual double rightIntegralInverseForProbability(double * probability);
virtual double evaluateAtDiscreteAbscissa(int k) const;
protected:
constexpr static int k_maxNumberOfOperations = 1000000;
constexpr static float k_maxProbability = 0.9995f;
constexpr static double k_maxProbability = 0.9995;
constexpr static float k_displayTopMarginRatio = 0.05f;
constexpr static float k_displayBottomMarginRatio = 0.2f;
constexpr static float k_displayLeftMarginRatio = 0.05f;

View File

@@ -75,7 +75,7 @@ float NormalLaw::evaluateAtAbscissa(float x) const {
return (1.0f/(std::fabs(m_parameter2)*std::sqrt(2.0f*M_PI)))*std::exp(-0.5f*std::pow((x-m_parameter1)/m_parameter2,2));
}
bool NormalLaw::authorizedValueAtIndex(float x, int index) const {
bool NormalLaw::authorizedValueAtIndex(double x, int index) const {
if (index == 0) {
return true;
}
@@ -92,46 +92,46 @@ void NormalLaw::setParameterAtIndex(float f, int index) {
}
}
float NormalLaw::cumulativeDistributiveFunctionAtAbscissa(float x) const {
double NormalLaw::cumulativeDistributiveFunctionAtAbscissa(double x) const {
if (m_parameter2 == 0.0f) {
return NAN;
}
return standardNormalCumulativeDistributiveFunctionAtAbscissa((x-m_parameter1)/std::fabs(m_parameter2));
}
float NormalLaw::cumulativeDistributiveInverseForProbability(float * probability) {
double NormalLaw::cumulativeDistributiveInverseForProbability(double * probability) {
if (m_parameter2 == 0.0f) {
return NAN;
}
return standardNormalCumulativeDistributiveInverseForProbability(*probability)*std::fabs(m_parameter2) + m_parameter1;
}
float NormalLaw::standardNormalCumulativeDistributiveFunctionAtAbscissa(float abscissa) const {
if (abscissa == 0.0f) {
return 0.5f;
double NormalLaw::standardNormalCumulativeDistributiveFunctionAtAbscissa(double abscissa) const {
if (abscissa == 0.0) {
return 0.5;
}
if (abscissa < 0.0f) {
return 1.0f - standardNormalCumulativeDistributiveFunctionAtAbscissa(-abscissa);
if (abscissa < 0.0) {
return 1.0 - standardNormalCumulativeDistributiveFunctionAtAbscissa(-abscissa);
}
if (abscissa > k_boundStandardNormalDistribution) {
return 1.0f;
return 1.0;
}
/* Waissi & Rossin's formula (error less than 0.0001) */
return 1.0f/(1.0f+std::exp(-std::sqrt(M_PI)*(k_beta1*std::pow(abscissa,5)+k_beta2*std::pow(abscissa,3)+k_beta3*abscissa)));
return 1.0/(1.0+std::exp(-std::sqrt(M_PI)*(k_beta1*std::pow(abscissa,5.0)+k_beta2*std::pow(abscissa,3.0)+k_beta3*abscissa)));
}
float NormalLaw::standardNormalCumulativeDistributiveInverseForProbability(float probability) {
if (probability >= 1.0f) {
double NormalLaw::standardNormalCumulativeDistributiveInverseForProbability(double probability) {
if (probability >= 1.0) {
return INFINITY;
}
if (probability <= 0.0f) {
if (probability <= 0.0) {
return -INFINITY;
}
if (probability < 0.5f) {
if (probability < 0.5) {
return -standardNormalCumulativeDistributiveInverseForProbability(1-probability);
}
/* Soranzo & Epure (error less than 0.001) */
return (k_alpha3/std::log(k_alpha2))*std::log(1.0f - std::log(-std::log(probability)/std::log(2.0f))/std::log(k_alpha1));
return (k_alpha3/std::log(k_alpha2))*std::log(1.0 - std::log(-std::log(probability)/std::log(2.0))/std::log(k_alpha1));
}

View File

@@ -18,22 +18,22 @@ public:
I18n::Message parameterNameAtIndex(int index) override;
I18n::Message parameterDefinitionAtIndex(int index) override;
float evaluateAtAbscissa(float x) const override;
bool authorizedValueAtIndex(float x, int index) const override;
bool authorizedValueAtIndex(double x, int index) const override;
void setParameterAtIndex(float f, int index) override;
float cumulativeDistributiveFunctionAtAbscissa(float x) const override;
float cumulativeDistributiveInverseForProbability(float * probability) override;
double cumulativeDistributiveFunctionAtAbscissa(double x) const override;
double cumulativeDistributiveInverseForProbability(double * probability) override;
private:
constexpr static float k_maxRatioMuSigma = 1000.0f;
constexpr static double k_maxRatioMuSigma = 1000.0f;
/* Waissi & Rossin constants */
constexpr static float k_beta1 = -0.0004406f;
constexpr static float k_beta2 = 0.0418198f;
constexpr static float k_beta3 = 0.9f;
constexpr static float k_boundStandardNormalDistribution = 3.291f;
constexpr static float k_alpha1 = 22.0f;
constexpr static float k_alpha2 = 41.0f;
constexpr static float k_alpha3 = 10.0f;
float standardNormalCumulativeDistributiveFunctionAtAbscissa(float abscissa) const;
float standardNormalCumulativeDistributiveInverseForProbability(float probability);
constexpr static double k_beta1 = -0.0004406;
constexpr static double k_beta2 = 0.0418198;
constexpr static double k_beta3 = 0.9;
constexpr static double k_boundStandardNormalDistribution = 3.291;
constexpr static double k_alpha1 = 22.0;
constexpr static double k_alpha2 = 41.0;
constexpr static double k_alpha3 = 10.0;
double standardNormalCumulativeDistributiveFunctionAtAbscissa(double abscissa) const;
double standardNormalCumulativeDistributiveInverseForProbability(double probability);
};
}

View File

@@ -59,12 +59,12 @@ float PoissonLaw::evaluateAtAbscissa(float x) const {
if (x < 0.0f) {
return NAN;
}
float lResult = -m_parameter1+(int)x*std::log(m_parameter1)-std::lgamma(floorf(x)+1.0f);
float lResult = -m_parameter1+std::floor(x)*std::log(m_parameter1)-std::lgamma(std::floor(x)+1);
return std::exp(lResult);
}
bool PoissonLaw::authorizedValueAtIndex(float x, int index) const {
if (x <= 0.0f || x > 999.0f) {
bool PoissonLaw::authorizedValueAtIndex(double x, int index) const {
if (x <= 0.0 || x > 999.0) {
return false;
}
return true;

View File

@@ -18,7 +18,7 @@ public:
I18n::Message parameterNameAtIndex(int index) override;
I18n::Message parameterDefinitionAtIndex(int index) override;
float evaluateAtAbscissa(float x) const override;
bool authorizedValueAtIndex(float x, int index) const override;
bool authorizedValueAtIndex(double x, int index) const override;
};
}

View File

@@ -78,7 +78,7 @@ float UniformLaw::evaluateAtAbscissa(float t) const {
return 0.0f;
}
bool UniformLaw::authorizedValueAtIndex(float x, int index) const {
bool UniformLaw::authorizedValueAtIndex(double x, int index) const {
if (index == 0) {
return true;
}
@@ -95,17 +95,17 @@ void UniformLaw::setParameterAtIndex(float f, int index) {
}
}
float UniformLaw::cumulativeDistributiveFunctionAtAbscissa(float x) const {
double UniformLaw::cumulativeDistributiveFunctionAtAbscissa(double x) const {
if (x <= m_parameter1) {
return 0.0f;
return 0.0;
}
if (x < m_parameter2) {
return (x-m_parameter1)/(m_parameter2-m_parameter1);
}
return 1.0f;
return 1.0;
}
float UniformLaw::cumulativeDistributiveInverseForProbability(float * probability) {
double UniformLaw::cumulativeDistributiveInverseForProbability(double * probability) {
if (*probability >= 1.0f) {
return m_parameter2;
}

View File

@@ -18,10 +18,10 @@ public:
I18n::Message parameterNameAtIndex(int index) override;
I18n::Message parameterDefinitionAtIndex(int index) override;
float evaluateAtAbscissa(float x) const override;
bool authorizedValueAtIndex(float x, int index) const override;
bool authorizedValueAtIndex(double x, int index) const override;
void setParameterAtIndex(float f, int index) override;
float cumulativeDistributiveFunctionAtAbscissa(float x) const override;
float cumulativeDistributiveInverseForProbability(float * probability) override;
double cumulativeDistributiveFunctionAtAbscissa(double x) const override;
double cumulativeDistributiveInverseForProbability(double * probability) override;
private:
constexpr static float k_diracMaximum = 10.0f;
constexpr static float k_diracWidth = 0.001f;

View File

@@ -132,11 +132,11 @@ int ParametersController::reusableParameterCellCount(int type) {
return m_law->numberOfParameter();
}
float ParametersController::parameterAtIndex(int index) {
double ParametersController::parameterAtIndex(int index) {
return m_law->parameterValueAtIndex(index);
}
bool ParametersController::setParameterAtIndex(int parameterIndex, float f) {
bool ParametersController::setParameterAtIndex(int parameterIndex, double f) {
if (!m_law->authorizedValueAtIndex(f, parameterIndex)) {
app()->displayWarning(I18n::Message::ForbiddenValue);
return false;

View File

@@ -22,8 +22,8 @@ private:
HighlightCell * reusableParameterCell(int index, int type) override;
int reusableParameterCellCount(int type) override;
void buttonAction() override;
float parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, float f) override;
double parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
I18n::Message okButtonText() override;
View * loadView() override;

View File

@@ -153,13 +153,13 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
if (i == 1 && j > 0 && j <= k_totalNumberOfDoubleBufferRows) {
ArgCalculPointer calculationMethods[k_totalNumberOfDoubleBufferRows] = {&Store::meanOfColumn, &Store::sumOfColumn,
&Store::squaredValueSumOfColumn, &Store::standardDeviationOfColumn, &Store::varianceOfColumn};
float calculation1 = (m_store->*calculationMethods[j-1])(0);
float calculation2 = (m_store->*calculationMethods[j-1])(1);
double calculation1 = (m_store->*calculationMethods[j-1])(0);
double calculation2 = (m_store->*calculationMethods[j-1])(1);
EvenOddDoubleBufferTextCell * myCell = (EvenOddDoubleBufferTextCell *)cell;
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
Complex<float>::convertFloatToText(calculation1, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
Complex<double>::convertFloatToText(calculation1, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
myCell->setFirstText(buffer);
Complex<float>::convertFloatToText(calculation2, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
Complex<double>::convertFloatToText(calculation2, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
myCell->setSecondText(buffer);
return;
}
@@ -172,10 +172,10 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
assert(j != 9);
CalculPointer calculationMethods[k_totalNumberOfRows-k_totalNumberOfDoubleBufferRows] = {&Store::numberOfPairs, &Store::covariance,
&Store::columnProductSum, nullptr, &Store::slope, &Store::yIntercept, &Store::correlationCoefficient, &Store::squaredCorrelationCoefficient};
float calculation = (m_store->*calculationMethods[j-k_totalNumberOfDoubleBufferRows-1])();
double calculation = (m_store->*calculationMethods[j-k_totalNumberOfDoubleBufferRows-1])();
EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell;
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
Complex<float>::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
Complex<double>::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
myCell->setText(buffer);
return;
}

View File

@@ -29,7 +29,7 @@ const char * GoToParameterController::title() {
return I18n::translate(I18n::Message::YPrediction);
}
float GoToParameterController::parameterAtIndex(int index) {
double GoToParameterController::parameterAtIndex(int index) {
assert(index == 0);
if (m_xPrediction) {
return m_cursor->x();
@@ -37,13 +37,13 @@ float GoToParameterController::parameterAtIndex(int index) {
return m_cursor->y();
}
bool GoToParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool GoToParameterController::setParameterAtIndex(int parameterIndex, double f) {
assert(parameterIndex == 0);
if (std::fabs(f) > k_maxDisplayableFloat) {
app()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
float x = m_store->xValueForYValue(f);
double x = m_store->xValueForYValue(f);
if (m_xPrediction) {
x = m_store->yValueForXValue(f);
}
@@ -52,7 +52,7 @@ bool GoToParameterController::setParameterAtIndex(int parameterIndex, float f) {
return false;
}
if (isnan(x)) {
if (m_store->slope() < FLT_EPSILON && f == m_store->yIntercept()) {
if (m_store->slope() < DBL_EPSILON && f == m_store->yIntercept()) {
m_graphController->selectRegressionCurve();
m_cursor->moveTo(m_cursor->x(), f);
return true;

View File

@@ -16,8 +16,8 @@ public:
const char * title() override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
private:
float parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, float f) override;
double parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
Store * m_store;
bool m_xPrediction;
GraphController * m_graphController;

View File

@@ -88,7 +88,7 @@ void GraphController::reloadBannerView() {
numberOfChar = 0;
legend = "x=";
float x = m_cursor->x();
double x = m_cursor->x();
// Display a specific legend if the mean dot is selected
if (*m_selectedDotIndex == m_store->numberOfPairs()) {
constexpr static char legX[] = {Ion::Charset::XBar, '=', 0};
@@ -98,7 +98,7 @@ void GraphController::reloadBannerView() {
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
numberOfChar += Complex<float>::convertFloatToText(x, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
numberOfChar += Complex<double>::convertFloatToText(x, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -107,7 +107,7 @@ void GraphController::reloadBannerView() {
numberOfChar = 0;
legend = "y=";
float y = m_cursor->y();
double y = m_cursor->y();
if (*m_selectedDotIndex == m_store->numberOfPairs()) {
constexpr static char legY[] = {Ion::Charset::YBar, '=', 0};
legend = legY;
@@ -116,7 +116,7 @@ void GraphController::reloadBannerView() {
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
numberOfChar += Complex<float>::convertFloatToText(y, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
numberOfChar += Complex<double>::convertFloatToText(y, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::MediumNumberOfSignificantDigits), Constant::MediumNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -125,11 +125,11 @@ void GraphController::reloadBannerView() {
numberOfChar = 0;
legend = " a=";
float slope = m_store->slope();
double slope = m_store->slope();
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
numberOfChar += Complex<float>::convertFloatToText(slope, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += Complex<double>::convertFloatToText(slope, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -138,11 +138,11 @@ void GraphController::reloadBannerView() {
numberOfChar = 0;
legend = " b=";
float yIntercept = m_store->yIntercept();
double yIntercept = m_store->yIntercept();
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
numberOfChar += Complex<float>::convertFloatToText(yIntercept, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += Complex<double>::convertFloatToText(yIntercept, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -151,11 +151,11 @@ void GraphController::reloadBannerView() {
numberOfChar = 0;
legend = " r=";
float r = m_store->correlationCoefficient();
double r = m_store->correlationCoefficient();
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
numberOfChar += Complex<float>::convertFloatToText(r, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += Complex<double>::convertFloatToText(r, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -164,11 +164,11 @@ void GraphController::reloadBannerView() {
numberOfChar = 0;
legend = " r2=";
float r2 = m_store->squaredCorrelationCoefficient();
double r2 = m_store->squaredCorrelationCoefficient();
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
numberOfChar += Complex<float>::convertFloatToText(r2, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
numberOfChar += Complex<double>::convertFloatToText(r2, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -181,8 +181,8 @@ void GraphController::initRangeParameters() {
}
void GraphController::initCursorParameters() {
float x = (m_store->xMin() + m_store->xMax())/2.0f;
float y = m_store->yValueForXValue(x);
double x = (m_store->xMin() + m_store->xMax())/2.0;
double y = m_store->yValueForXValue(x);
m_cursor->moveTo(x, y);
m_store->panToMakePointVisible(x, y, k_cursorTopMarginRatio, k_cursorRightMarginRatio, k_cursorBottomMarginRatio, k_cursorLeftMarginRatio);
selectRegressionCurve();
@@ -205,16 +205,16 @@ bool GraphController::moveCursorHorizontally(int direction) {
}
return false;
}
float x = direction > 0 ? m_cursor->x() + m_store->xGridUnit()/k_numberOfCursorStepsInGradUnit :
double x = direction > 0 ? m_cursor->x() + m_store->xGridUnit()/k_numberOfCursorStepsInGradUnit :
m_cursor->x() - m_store->xGridUnit()/k_numberOfCursorStepsInGradUnit;
float y = m_store->yValueForXValue(x);
double y = m_store->yValueForXValue(x);
m_cursor->moveTo(x, y);
m_store->panToMakePointVisible(x, y, k_cursorTopMarginRatio, k_cursorRightMarginRatio, k_cursorBottomMarginRatio, k_cursorLeftMarginRatio);
return true;
}
bool GraphController::moveCursorVertically(int direction) {
float yRegressionCurve = m_store->yValueForXValue(m_cursor->x());
double yRegressionCurve = m_store->yValueForXValue(m_cursor->x());
if (*m_selectedDotIndex >= 0) {
if ((yRegressionCurve - m_cursor->y() > 0) == (direction > 0)) {
*m_selectedDotIndex = -1;

View File

@@ -9,7 +9,9 @@ GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * banne
CurveView(store, cursor, bannerView, cursorView),
m_store(store),
m_xLabels{},
m_yLabels{}
m_yLabels{},
m_slope(NAN),
m_yIntercept(NAN)
{
}
@@ -20,6 +22,8 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
drawAxes(ctx, rect, Axis::Vertical);
drawLabels(ctx, rect, Axis::Horizontal, true);
drawLabels(ctx, rect, Axis::Vertical, true);
m_slope = m_store->slope();
m_yIntercept = m_store->yIntercept();
drawCurve(ctx, rect, nullptr, Palette::YellowDark);
for (int index = 0; index < m_store->numberOfPairs(); index++) {
drawDot(ctx, rect, m_store->get(0,index), m_store->get(1,index), Palette::Red);
@@ -36,7 +40,7 @@ char * GraphView::label(Axis axis, int index) const {
}
float GraphView::evaluateModelWithParameter(Model * curve, float t) const {
return m_store->yValueForXValue(t);
return m_slope*t+m_yIntercept;
}
}

View File

@@ -18,6 +18,11 @@ private:
Store * m_store;
char m_xLabels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)];
char m_yLabels[k_maxNumberOfYLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)];
/* We memoize the a and b of the regression y = ax+b to avoid recomputing them
* for each stamp of the curve (since the computation is done with double
* precision) */
mutable float m_slope;
mutable float m_yIntercept;
};
}

View File

@@ -119,7 +119,7 @@ void Store::setDefault() {
/* Calculations */
float Store::numberOfPairs() {
double Store::numberOfPairs() {
return m_numberOfPairs;
}
@@ -143,73 +143,73 @@ float Store::minValueOfColumn(int i) {
return min;
}
float Store::squaredValueSumOfColumn(int i) {
float result = 0;
double Store::squaredValueSumOfColumn(int i) {
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[i][k]*m_data[i][k];
}
return result;
}
float Store::columnProductSum() {
float result = 0;
double Store::columnProductSum() {
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[0][k]*m_data[1][k];
}
return result;
}
float Store::meanOfColumn(int i) {
double Store::meanOfColumn(int i) {
return sumOfColumn(i)/m_numberOfPairs;
}
float Store::varianceOfColumn(int i) {
float mean = meanOfColumn(i);
double Store::varianceOfColumn(int i) {
double mean = meanOfColumn(i);
return squaredValueSumOfColumn(i)/m_numberOfPairs - mean*mean;
}
float Store::standardDeviationOfColumn(int i) {
double Store::standardDeviationOfColumn(int i) {
return std::sqrt(varianceOfColumn(i));
}
float Store::covariance() {
double Store::covariance() {
return columnProductSum()/m_numberOfPairs - meanOfColumn(0)*meanOfColumn(1);
}
float Store::slope() {
double Store::slope() {
return covariance()/varianceOfColumn(0);
}
float Store::yIntercept() {
double Store::yIntercept() {
return meanOfColumn(1) - slope()*meanOfColumn(0);
}
float Store::yValueForXValue(float x) {
double Store::yValueForXValue(double x) {
return slope()*x+yIntercept();
}
float Store::xValueForYValue(float y) {
if (std::fabs(slope()) < FLT_EPSILON) {
double Store::xValueForYValue(double y) {
if (std::fabs(slope()) < DBL_EPSILON) {
return NAN;
}
return (y - yIntercept())/slope();
}
float Store::correlationCoefficient() {
float sd0 = standardDeviationOfColumn(0);
float sd1 = standardDeviationOfColumn(1);
if (sd0 == 0.0f || sd1 == 0.0f) {
return 1.0f;
double Store::correlationCoefficient() {
double sd0 = standardDeviationOfColumn(0);
double sd1 = standardDeviationOfColumn(1);
if (sd0 == 0.0 || sd1 == 0.0) {
return 1.0;
}
return covariance()/(sd0*sd1);
}
float Store::squaredCorrelationCoefficient() {
float cov = covariance();
float v0 = varianceOfColumn(0);
float v1 = varianceOfColumn(1);
if (v0 == 0.0f || v1 == 0.0f) {
return 1.0f;
double Store::squaredCorrelationCoefficient() {
double cov = covariance();
double v0 = varianceOfColumn(0);
double v1 = varianceOfColumn(1);
if (v0 == 0.0 || v1 == 0.0) {
return 1.0;
}
return cov*cov/(v0*v1);
}

View File

@@ -21,19 +21,19 @@ public:
void setDefault() override;
// Calculation
float numberOfPairs();
float squaredValueSumOfColumn(int i);
float columnProductSum();
float meanOfColumn(int i);
float varianceOfColumn(int i);
float standardDeviationOfColumn(int i);
float covariance();
float slope();
float yIntercept();
float yValueForXValue(float x);
float xValueForYValue(float y);
float correlationCoefficient();
float squaredCorrelationCoefficient();
double numberOfPairs();
double squaredValueSumOfColumn(int i);
double columnProductSum();
double meanOfColumn(int i);
double varianceOfColumn(int i);
double standardDeviationOfColumn(int i);
double covariance();
double slope();
double yIntercept();
double yValueForXValue(double x);
double xValueForYValue(double y);
double correlationCoefficient();
double squaredCorrelationCoefficient();
private:
constexpr static float k_displayTopMarginRatio = 0.12f;
constexpr static float k_displayRightMarginRatio = 0.05f;
@@ -45,8 +45,8 @@ private:
float minValueOfColumn(int i);
};
typedef float (Store::*ArgCalculPointer)(int);
typedef float (Store::*CalculPointer)();
typedef double (Store::*ArgCalculPointer)(int);
typedef double (Store::*CalculPointer)();
typedef void (Store::*RangeMethodPointer)();
}

View File

@@ -5,7 +5,7 @@
namespace Sequence {
bool GoToParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool GoToParameterController::setParameterAtIndex(int parameterIndex, double f) {
assert(parameterIndex == 0);
return Shared::FunctionGoToParameterController::setParameterAtIndex(parameterIndex, std::round(f));
}

View File

@@ -9,7 +9,7 @@ class GoToParameterController : public Shared::FunctionGoToParameterController {
public:
using Shared::FunctionGoToParameterController::FunctionGoToParameterController;
private:
bool setParameterAtIndex(int parameterIndex, float f) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
};
}

View File

@@ -46,34 +46,34 @@ bool GraphController::handleEnter() {
}
bool GraphController::moveCursorHorizontally(int direction) {
float xCursorPosition = std::round(m_cursor->x());
double xCursorPosition = std::round(m_cursor->x());
if (direction < 0 && xCursorPosition <= 0) {
return false;
}
/* The cursor moves by step of at minimum 1. If the windowRange is to large
* compared to the resolution, the cursor takes bigger round step to cross
* the window in approximatively resolution steps. */
float step = std::ceil((interactiveCurveViewRange()->xMax()-interactiveCurveViewRange()->xMin())/m_view.resolution());
step = step < 1.0f ? 1.0f : step;
float x = direction > 0 ? xCursorPosition + step:
double step = std::ceil((interactiveCurveViewRange()->xMax()-interactiveCurveViewRange()->xMin())/m_view.resolution());
step = step < 1.0 ? 1.0 : step;
double x = direction > 0 ? xCursorPosition + step:
xCursorPosition - step;
if (x < 0.0f) {
if (x < 0.0) {
return false;
}
Sequence * s = m_sequenceStore->activeFunctionAtIndex(m_indexFunctionSelectedByCursor);
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
float y = s->evaluateAtAbscissa(x, myApp->localContext());
double y = s->evaluateAtAbscissa(x, myApp->localContext());
m_cursor->moveTo(x, y);
m_graphRange->panToMakePointVisible(x, y, k_cursorTopMarginRatio, k_cursorRightMarginRatio, k_cursorBottomMarginRatio, k_cursorLeftMarginRatio);
return true;
}
void GraphController::initCursorParameters() {
float x = std::round((interactiveCurveViewRange()->xMin()+interactiveCurveViewRange()->xMax())/2.0f);
double x = std::round((interactiveCurveViewRange()->xMin()+interactiveCurveViewRange()->xMax())/2.0);
m_indexFunctionSelectedByCursor = 0;
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
int functionIndex = 0;
float y = 0;
double y = 0;
do {
Sequence * firstFunction = m_sequenceStore->activeFunctionAtIndex(functionIndex++);
y = firstFunction->evaluateAtAbscissa(x, myApp->localContext());

View File

@@ -64,14 +64,14 @@ bool TermSumController::handleEvent(Ion::Events::Event event) {
if (m_step > 0 && m_startSum >= m_cursor->x()) {
return false;
}
if (moveCursorHorizontallyToPosition(std::round(m_cursor->x()-1.0f))) {
if (moveCursorHorizontallyToPosition(std::round(m_cursor->x()-1.0))) {
m_graphView->reload();
return true;
}
return false;
}
if (event == Ion::Events::Right) {
if (moveCursorHorizontallyToPosition(std::round(m_cursor->x()+1.0f))) {
if (moveCursorHorizontallyToPosition(std::round(m_cursor->x()+1.0))) {
m_graphView->reload();
return true;
}
@@ -106,7 +106,7 @@ bool TermSumController::handleEvent(Ion::Events::Event event) {
m_step++;
m_endSum = m_cursor->x();
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
float sum = m_sequence->sumOfTermsBetweenAbscissa(m_startSum, m_endSum, myApp->localContext());
double sum = m_sequence->sumOfTermsBetweenAbscissa(m_startSum, m_endSum, myApp->localContext());
m_legendView.setSumResult(m_sequence->name(), sum);
m_legendView.setLegendMessage(I18n::Message::Default);
m_graphView->setHighlightColor(true);
@@ -140,12 +140,12 @@ bool TermSumController::moveCursorHorizontallyToPosition(int position) {
if (position < 0) {
return false;
}
float x = position;
double x = position;
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
if (m_sequence == nullptr) {
return false;
}
float y = m_sequence->evaluateAtAbscissa(x, myApp->localContext());
double y = m_sequence->evaluateAtAbscissa(x, myApp->localContext());
m_cursor->moveTo(x, y);
if (m_step == 0) {
m_legendView.setSumSubscript(m_cursor->x());
@@ -199,7 +199,7 @@ void TermSumController::LegendView::setSumSubscript(float start) {
}
const char sigma[3] = {' ',Ion::Charset::CapitalSigma, 0};
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
Complex<double>::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal);
Complex<float>::convertFloatToText(start, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal);
m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, 2), new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small), nullptr);
m_sum.setExpression(m_sumLayout);
m_sum.setAlignment(0.0f, 0.5f);
@@ -214,17 +214,17 @@ void TermSumController::LegendView::setSumSuperscript(float start, float end) {
char bufferStart[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
Complex<float>::convertFloatToText(start, bufferStart, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal);
char bufferEnd[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
Complex<double>::convertFloatToText(end, bufferEnd, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal);
Complex<float>::convertFloatToText(end, bufferEnd, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, Expression::FloatDisplayMode::Decimal);
m_sumLayout = new CondensedSumLayout(new StringLayout(sigma, 2), new StringLayout(bufferStart, strlen(bufferStart), KDText::FontSize::Small), new StringLayout(bufferEnd, strlen(bufferEnd), KDText::FontSize::Small));
m_sum.setExpression(m_sumLayout);
m_sum.setAlignment(0.0f, 0.5f);
}
void TermSumController::LegendView::setSumResult(const char * sequenceName, float result) {
void TermSumController::LegendView::setSumResult(const char * sequenceName, double result) {
ExpressionLayout * childrenLayouts[3];
char buffer[2+PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
strlcpy(buffer, "= ", 3);
Complex<float>::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
Complex<double>::convertFloatToText(result, buffer+2, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
childrenLayouts[2] = new StringLayout(buffer, strlen(buffer), KDText::FontSize::Small);
childrenLayouts[1] = new BaselineRelativeLayout(new StringLayout(sequenceName, 1, KDText::FontSize::Small), new StringLayout("n", 1, KDText::FontSize::Small), BaselineRelativeLayout::Type::Subscript);
childrenLayouts[0] = m_sumLayout;

View File

@@ -35,7 +35,7 @@ private:
void setLegendMessage(I18n::Message message);
void setSumSubscript(float start);
void setSumSuperscript(float start, float end);
void setSumResult(const char * sequenceName, float result);
void setSumResult(const char * sequenceName, double result);
KDSize minimalSizeForOptimalDisplay() const override;
private:
constexpr static KDCoordinate k_legendHeight = 35;

View File

@@ -20,12 +20,12 @@ void IntervalParameterController::willDisplayCellForIndex(HighlightCell * cell,
FloatParameterController::willDisplayCellForIndex(cell, index);
}
bool IntervalParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool IntervalParameterController::setParameterAtIndex(int parameterIndex, double f) {
if (f < 0) {
app()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
float parameter = std::round(f);
double parameter = std::round(f);
if (parameterIndex == 2 && parameter == 0.0f) {
parameter = 1.0f;
}

View File

@@ -9,7 +9,7 @@ class IntervalParameterController : public Shared::IntervalParameterController {
public:
IntervalParameterController(Responder * parentResponder, Shared::Interval * interval);
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
bool setParameterAtIndex(int parameterIndex, float f) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
};
}

View File

@@ -46,7 +46,7 @@ IntervalParameterController * ValuesController::intervalParameterController() {
return &m_intervalParameterController;
}
bool ValuesController::setDataAtLocation(float floatBody, int columnIndex, int rowIndex) {
bool ValuesController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) {
if (floatBody < 0) {
return false;
}

View File

@@ -15,7 +15,7 @@ public:
I18n::Message emptyMessage() override;
IntervalParameterController * intervalParameterController() override;
private:
bool setDataAtLocation(float floatBody, int columnIndex, int rowIndex) override;
bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override;
int maxNumberOfCells() override;
int maxNumberOfFunctions() override;
constexpr static int k_maxNumberOfCells = 30;

View File

@@ -9,22 +9,22 @@ CurveViewCursor::CurveViewCursor() :
{
}
float CurveViewCursor::x() {
double CurveViewCursor::x() {
return m_x;
}
float CurveViewCursor::y() {
double CurveViewCursor::y() {
return m_y;
}
void CurveViewCursor::moveTo(float x, float y) {
void CurveViewCursor::moveTo(double x, double y) {
m_x = clipped(x, false);
m_y = clipped(y, true);
}
float CurveViewCursor::clipped(float x, bool canBeInfinite) {
float maxValue = canBeInfinite ? INFINITY : k_maxFloat;
float clippedX = x > k_maxFloat ? maxValue : x;
double CurveViewCursor::clipped(double x, bool canBeInfinite) {
double maxValue = canBeInfinite ? INFINITY : k_maxFloat;
double clippedX = x > k_maxFloat ? maxValue : x;
clippedX = clippedX < - k_maxFloat ? -maxValue : clippedX;
return clippedX;
}

View File

@@ -6,14 +6,14 @@ namespace Shared {
class CurveViewCursor {
public:
CurveViewCursor();
float x();
float y();
void moveTo(float x, float y);
double x();
double y();
void moveTo(double x, double y);
private:
static float clipped(float f, bool canBeInfinite);
constexpr static float k_maxFloat = 1E+8f;
float m_x;
float m_y;
static double clipped(double f, bool canBeInfinite);
constexpr static double k_maxFloat = 1E+8;
double m_x;
double m_y;
};
}

View File

@@ -23,7 +23,7 @@ bool EditableCellTableViewController::textFieldShouldFinishEditing(TextField * t
bool EditableCellTableViewController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
Context * globalContext = appsContainer->globalContext();
float floatBody = Expression::approximate<float>(text, *globalContext);
double floatBody = Expression::approximate<double>(text, *globalContext);
if (isnan(floatBody) || isinf(floatBody)) {
app()->displayWarning(I18n::Message::UndefinedValue);
return false;
@@ -93,7 +93,7 @@ void EditableCellTableViewController::willDisplayCellAtLocationWithDisplayMode(H
}
if (!myEditableValueCell->isEditing()) {
myCell->setEven(j%2 == 0);
Complex<float>::convertFloatToText(dataAtLocation(i, j), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, floatDisplayMode);
Complex<double>::convertFloatToText(dataAtLocation(i, j), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits, floatDisplayMode);
myEditableValueCell->setText(buffer);
}
return;

View File

@@ -25,8 +25,8 @@ private:
TextFieldDelegateApp * textFieldDelegateApp() override;
static constexpr KDCoordinate k_cellHeight = 20;
virtual bool cellAtLocationIsEditable(int columnIndex, int rowIndex) = 0;
virtual bool setDataAtLocation(float floatBody, int columnIndex, int rowIndex) = 0;
virtual float dataAtLocation(int columnIndex, int rowIndex) = 0;
virtual bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) = 0;
virtual double dataAtLocation(int columnIndex, int rowIndex) = 0;
virtual int numberOfElements() = 0;
virtual int maxNumberOfElements() const = 0;
};

View File

@@ -12,12 +12,12 @@ FloatPairStore::FloatPairStore() :
{
}
float FloatPairStore::get(int i, int j) {
double FloatPairStore::get(int i, int j) {
assert(j < m_numberOfPairs);
return m_data[i][j];
}
void FloatPairStore::set(float f, int i, int j) {
void FloatPairStore::set(double f, int i, int j) {
if (j >= k_maxNumberOfPairs) {
return;
}
@@ -51,8 +51,8 @@ void FloatPairStore::resetColumn(int i) {
}
}
float FloatPairStore::sumOfColumn(int i) {
float result = 0;
double FloatPairStore::sumOfColumn(int i) {
double result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[i][k];
}
@@ -60,13 +60,13 @@ float FloatPairStore::sumOfColumn(int i) {
}
uint32_t FloatPairStore::storeChecksum() {
size_t dataLengthInBytes = k_maxNumberOfPairs*2*sizeof(float);
size_t dataLengthInBytes = 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>>2);
}
float FloatPairStore::defaultValue(int i) {
return 0.0f;
double FloatPairStore::defaultValue(int i) {
return 0.0;
}
}

View File

@@ -10,19 +10,19 @@ public:
FloatPairStore();
// Delete the implicit copy constructor: the object is heavy
FloatPairStore(const FloatPairStore&) = delete;
float get(int i, int j);
void set(float f, int i, int j);
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);
float sumOfColumn(int i);
double sumOfColumn(int i);
uint32_t storeChecksum();
constexpr static int k_maxNumberOfPairs = 100;
protected:
virtual float defaultValue(int ii);
virtual double defaultValue(int i);
int m_numberOfPairs;
float m_data[2][k_maxNumberOfPairs];
double m_data[2][k_maxNumberOfPairs];
};
}

View File

@@ -118,7 +118,7 @@ bool FloatParameterController::textFieldShouldFinishEditing(TextField * textFiel
bool FloatParameterController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
AppsContainer * appsContainer = ((TextFieldDelegateApp *)app())->container();
Context * globalContext = appsContainer->globalContext();
float floatBody = Expression::approximate<float>(text, *globalContext);
double floatBody = Expression::approximate<double>(text, *globalContext);
if (isnan(floatBody) || isinf(floatBody)) {
app()->displayWarning(I18n::Message::UndefinedValue);
return false;

View File

@@ -32,7 +32,7 @@ public:
protected:
int activeCell();
StackViewController * stackController();
virtual float parameterAtIndex(int index) = 0;
virtual double parameterAtIndex(int index) = 0;
virtual SelectableTableView * selectableTableView();
View * loadView() override;
void unloadView(View * view) override;
@@ -43,7 +43,7 @@ private:
virtual int reusableParameterCellCount(int type) = 0;
virtual HighlightCell * reusableParameterCell(int index, int type) = 0;
TextFieldDelegateApp * textFieldDelegateApp() override;
virtual bool setParameterAtIndex(int parameterIndex, float f) = 0;
virtual bool setParameterAtIndex(int parameterIndex, double f) = 0;
ButtonWithSeparator * m_okButton;
};

View File

@@ -15,12 +15,12 @@ const char * FunctionGoToParameterController::title() {
return I18n::translate(I18n::Message::Goto);
}
float FunctionGoToParameterController::parameterAtIndex(int index) {
double FunctionGoToParameterController::parameterAtIndex(int index) {
assert(index == 0);
return m_cursor->x();
}
bool FunctionGoToParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool FunctionGoToParameterController::setParameterAtIndex(int parameterIndex, double f) {
assert(parameterIndex == 0);
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
float y = m_function->evaluateAtAbscissa(f, myApp->localContext());

View File

@@ -12,10 +12,10 @@ public:
const char * title() override;
void setFunction(Function * function);
protected:
bool setParameterAtIndex(int parameterIndex, float f) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
Function * m_function;
private:
float parameterAtIndex(int index) override;
double parameterAtIndex(int index) override;
};
}

View File

@@ -125,12 +125,12 @@ void FunctionGraphController::initRangeParameters() {
bool FunctionGraphController::moveCursorVertically(int direction) {
Function * actualFunction = functionStore()->activeFunctionAtIndex(m_indexFunctionSelectedByCursor);
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
float y = actualFunction->evaluateAtAbscissa(m_cursor->x(), myApp->localContext());
double y = actualFunction->evaluateAtAbscissa(m_cursor->x(), myApp->localContext());
Function * nextFunction = actualFunction;
float nextY = direction > 0 ? FLT_MAX : -FLT_MAX;
double nextY = direction > 0 ? DBL_MAX : -DBL_MAX;
for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) {
Function * f = functionStore()->activeFunctionAtIndex(i);
float newY = f->evaluateAtAbscissa(m_cursor->x(), myApp->localContext());
double newY = f->evaluateAtAbscissa(m_cursor->x(), myApp->localContext());
bool isNextFunction = direction > 0 ? (newY > y && newY < nextY) : (newY < y && newY > nextY);
if (isNextFunction) {
m_indexFunctionSelectedByCursor = i;

View File

@@ -14,7 +14,7 @@ public:
int numberOfRows() override;
bool handleEvent(Ion::Events::Event event) override;
protected:
constexpr static float k_maxDisplayableFloat = 1E8f;
constexpr static double k_maxDisplayableFloat = 1E8;
CurveViewCursor * m_cursor;
InteractiveCurveViewRange * m_graphRange;
private:

View File

@@ -24,40 +24,40 @@ void Interval::deleteElementAtIndex(int index) {
m_intervalBuffer[m_numberOfElements] = 0.0f;
}
float Interval::element(int i) {
double Interval::element(int i) {
assert(i >= 0 && i < numberOfElements());
computeElements();
return m_intervalBuffer[i];
}
float Interval::start() {
double Interval::start() {
return m_start;
}
float Interval::end() {
double Interval::end() {
return m_end;
}
float Interval::step() {
double Interval::step() {
return m_step;
}
void Interval::setStart(float f) {
void Interval::setStart(double f) {
m_start = f;
m_needCompute = true;
}
void Interval::setEnd(float f) {
void Interval::setEnd(double f) {
m_end = f;
m_needCompute = true;
}
void Interval::setStep(float f) {
void Interval::setStep(double f) {
m_step = f;
m_needCompute = true;
}
void Interval::setElement(int i, float f) {
void Interval::setElement(int i, double f) {
assert(i <= numberOfElements() && i < k_maxNumberOfElements);
computeElements();
m_intervalBuffer[i] = f;

View File

@@ -10,28 +10,28 @@ public:
Interval(const Interval&) = delete;
int numberOfElements();
void deleteElementAtIndex(int index);
float element(int i);
float start();
float end();
float step();
void setStart(float f);
void setEnd(float f);
void setStep(float f);
void setElement(int i, float f);
double element(int i);
double start();
double end();
double step();
void setStart(double f);
void setEnd(double f);
void setStep(double f);
void setElement(int i, double f);
// TODO: decide the max number of elements after optimization
constexpr static int k_maxNumberOfElements = 100;
private:
void computeElements();
int m_numberOfElements;
float m_intervalBuffer[k_maxNumberOfElements];
float m_start;
float m_end;
float m_step;
double m_intervalBuffer[k_maxNumberOfElements];
double m_start;
double m_end;
double m_step;
bool m_needCompute;
};
typedef void (Interval::*SetterPointer)(float);
typedef float (Interval::*GetterPointer)();
typedef void (Interval::*SetterPointer)(double);
typedef double (Interval::*GetterPointer)();
}

View File

@@ -32,24 +32,24 @@ Interval * IntervalParameterController::interval() {
return m_interval;
}
float IntervalParameterController::parameterAtIndex(int index) {
double IntervalParameterController::parameterAtIndex(int index) {
GetterPointer getters[k_totalNumberOfCell] = {&Interval::start, &Interval::end, &Interval::step};
return (m_interval->*getters[index])();
}
bool IntervalParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool IntervalParameterController::setParameterAtIndex(int parameterIndex, double f) {
if (f <= 0.0f && parameterIndex == 2) {
app()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
float start = parameterIndex == 0 ? f : m_interval->start();
float end = parameterIndex == 1 ? f : m_interval->end();
double start = parameterIndex == 0 ? f : m_interval->start();
double end = parameterIndex == 1 ? f : m_interval->end();
if (start > end) {
if (parameterIndex == 1) {
app()->displayWarning(I18n::Message::ForbiddenValue);
return false;
}
float g = f+1.0f;
double g = f+1.0;
m_interval->setEnd(g);
}
SetterPointer setters[k_totalNumberOfCell] = {&Interval::setStart, &Interval::setEnd, &Interval::setStep};

View File

@@ -16,13 +16,13 @@ public:
int numberOfRows() override;
protected:
constexpr static int k_totalNumberOfCell = 3;
bool setParameterAtIndex(int parameterIndex, float f) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
Interval * m_interval;
bool handleEvent(Ion::Events::Event event) override;
private:
HighlightCell * reusableParameterCell(int index, int type) override;
int reusableParameterCellCount(int type) override;
float parameterAtIndex(int index) override;
double parameterAtIndex(int index) override;
void buttonAction() override;
View * loadView() override;
void unloadView(View * view) override;

View File

@@ -92,14 +92,14 @@ bool RangeParameterController::handleEvent(Ion::Events::Event event) {
return FloatParameterController::handleEvent(event);
}
float RangeParameterController::parameterAtIndex(int parameterIndex) {
double RangeParameterController::parameterAtIndex(int parameterIndex) {
ParameterGetterPointer getters[k_numberOfTextCell] = {&InteractiveCurveViewRange::xMin,
&InteractiveCurveViewRange::xMax, &InteractiveCurveViewRange::yMin, &InteractiveCurveViewRange::yMax};
int index = parameterIndex > 2 ? parameterIndex - 1 : parameterIndex;
return (m_interactiveRange->*getters[index])();
}
bool RangeParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool RangeParameterController::setParameterAtIndex(int parameterIndex, double f) {
ParameterSetterPointer setters[k_numberOfTextCell] = {&InteractiveCurveViewRange::setXMin,
&InteractiveCurveViewRange::setXMax, &InteractiveCurveViewRange::setYMin, &InteractiveCurveViewRange::setYMax};
int index = parameterIndex > 2 ? parameterIndex - 1 : parameterIndex;

View File

@@ -20,8 +20,8 @@ public:
private:
HighlightCell * reusableParameterCell(int index, int type) override;
int reusableParameterCellCount(int type) override;
float parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, float f) override;
double parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
View * loadView() override;
void unloadView(View * view) override;
constexpr static int k_numberOfTextCell = 4;

View File

@@ -108,12 +108,12 @@ bool StoreController::cellAtLocationIsEditable(int columnIndex, int rowIndex) {
return false;
}
bool StoreController::setDataAtLocation(float floatBody, int columnIndex, int rowIndex) {
bool StoreController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) {
m_store->set(floatBody, columnIndex, rowIndex-1);
return true;
}
float StoreController::dataAtLocation(int columnIndex, int rowIndex) {
double StoreController::dataAtLocation(int columnIndex, int rowIndex) {
return m_store->get(columnIndex, rowIndex-1);
}

View File

@@ -30,8 +30,8 @@ protected:
View * loadView() override;
void unloadView(View * view) override;
bool cellAtLocationIsEditable(int columnIndex, int rowIndex) override;
bool setDataAtLocation(float floatBody, int columnIndex, int rowIndex) override;
float dataAtLocation(int columnIndex, int rowIndex) override;
bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override;
double dataAtLocation(int columnIndex, int rowIndex) override;
int numberOfElements() override;
int maxNumberOfElements() const override;
virtual HighlightCell * titleCells(int index) = 0;

View File

@@ -142,8 +142,8 @@ void ValuesController::willDisplayCellAtLocation(HighlightCell * cell, int i, in
}
// The cell is a value cell
EvenOddBufferTextCell * myValueCell = (EvenOddBufferTextCell *)cell;
float x = m_interval->element(j-1);
Complex<float>::convertFloatToText(evaluationOfAbscissaAtColumn(x, i), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
double x = m_interval->element(j-1);
Complex<double>::convertFloatToText(evaluationOfAbscissaAtColumn(x, i), buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
myValueCell->setText(buffer);
}
}
@@ -280,12 +280,12 @@ bool ValuesController::cellAtLocationIsEditable(int columnIndex, int rowIndex) {
return false;
}
bool ValuesController::setDataAtLocation(float floatBody, int columnIndex, int rowIndex) {
bool ValuesController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) {
m_interval->setElement(rowIndex-1, floatBody);
return true;
}
float ValuesController::dataAtLocation(int columnIndex, int rowIndex) {
double ValuesController::dataAtLocation(int columnIndex, int rowIndex) {
return m_interval->element(rowIndex-1);
}
@@ -297,7 +297,7 @@ int ValuesController::maxNumberOfElements() const {
return Interval::k_maxNumberOfElements;
}
float ValuesController::evaluationOfAbscissaAtColumn(float abscissa, int columnIndex) {
double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int columnIndex) {
Function * function = functionAtColumn(columnIndex);
TextFieldDelegateApp * myApp = (TextFieldDelegateApp *)app();
return function->evaluateAtAbscissa(abscissa, myApp->localContext());

View File

@@ -44,7 +44,7 @@ public:
static constexpr KDCoordinate k_ordinateCellWidth = 100;
protected:
StackViewController * stackController() const;
bool setDataAtLocation(float floatBody, int columnIndex, int rowIndex) override;
bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override;
View * loadView() override;
void unloadView(View * view) override;
virtual void updateNumberOfColumns();
@@ -57,10 +57,10 @@ private:
void configureAbscissa();
void configureFunction();
bool cellAtLocationIsEditable(int columnIndex, int rowIndex) override;
float dataAtLocation(int columnIndex, int rowIndex) override;
double dataAtLocation(int columnIndex, int rowIndex) override;
int numberOfElements() override;
int maxNumberOfElements() const override;
virtual float evaluationOfAbscissaAtColumn(float abscissa, int columnIndex);
virtual double evaluationOfAbscissaAtColumn(double abscissa, int columnIndex);
constexpr static int k_maxNumberOfAbscissaCells = 10;
virtual int maxNumberOfCells() = 0;
virtual int maxNumberOfFunctions() = 0;

View File

@@ -52,9 +52,9 @@ bool ValuesParameterController::handleEvent(Ion::Events::Event event) {
case 0:
{
Interval * interval = m_intervalParameterController->interval();
interval->setEnd(0.0f);
interval->setStep(1.0f);
interval->setStart(1.0f);
interval->setEnd(0.0);
interval->setStep(1.0);
interval->setStart(1.0);
StackViewController * stack = ((StackViewController *)parentResponder());
stack->pop();
return true;

View File

@@ -70,8 +70,8 @@ void BoxController::reloadBannerView() {
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
CalculPointer calculationMethods[5] = {&Store::minValue, &Store::firstQuartile, &Store::median, &Store::thirdQuartile,
&Store::maxValue};
float calculation = (m_store->*calculationMethods[(int)m_view.selectedQuantile()])();
Complex<float>::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
double calculation = (m_store->*calculationMethods[(int)m_view.selectedQuantile()])();
Complex<double>::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
m_boxBannerView.setLegendAtIndex(buffer, 1);
}

View File

@@ -65,7 +65,7 @@ void BoxView::drawRect(KDContext * ctx, KDRect rect) const {
drawSegment(ctx, rect, Axis::Horizontal, 0.5f, m_store->minValue(), m_store->firstQuartile(), Palette::GreyDark);
drawSegment(ctx, rect, Axis::Horizontal, 0.5f, m_store->thirdQuartile(), m_store->maxValue(), Palette::GreyDark);
float calculations[5] = {m_store->minValue(), m_store->firstQuartile(), m_store->median(), m_store->thirdQuartile(), m_store->maxValue()};
double calculations[5] = {m_store->minValue(), m_store->firstQuartile(), m_store->median(), m_store->thirdQuartile(), m_store->maxValue()};
/* We then draw all the vertical lines of the box and then recolor the
* the selected quantile (if there is one). As two quantiles can have the same
* value, we cannot choose line colors and then color only once the vertical

View File

@@ -81,10 +81,10 @@ void CalculationController::willDisplayCellAtLocation(HighlightCell * cell, int
CalculPointer calculationMethods[k_totalNumberOfRows] = {&Store::sumOfOccurrences, &Store::minValue,
&Store::maxValue, &Store::range, &Store::mean, &Store::standardDeviation, &Store::variance, &Store::firstQuartile,
&Store::thirdQuartile, &Store::median, &Store::quartileRange, &Store::sum, &Store::squaredValueSum};
float calculation = (m_store->*calculationMethods[j])();
double calculation = (m_store->*calculationMethods[j])();
EvenOddBufferTextCell * myCell = (EvenOddBufferTextCell *)cell;
char buffer[PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits)];
Complex<float>::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
Complex<double>::convertFloatToText(calculation, buffer, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
myCell->setText(buffer);
}
}

View File

@@ -155,11 +155,11 @@ void HistogramController::reloadBannerView() {
int legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
float lowerBound = m_store->startOfBarAtIndex(*m_selectedBarIndex);
numberOfChar += Complex<float>::convertFloatToText(lowerBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
double lowerBound = m_store->startOfBarAtIndex(*m_selectedBarIndex);
numberOfChar += Complex<double>::convertFloatToText(lowerBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
buffer[numberOfChar++] = ';';
float upperBound = m_store->endOfBarAtIndex(*m_selectedBarIndex);
numberOfChar += Complex<float>::convertFloatToText(upperBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
double upperBound = m_store->endOfBarAtIndex(*m_selectedBarIndex);
numberOfChar += Complex<double>::convertFloatToText(upperBound, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
buffer[numberOfChar++] = '[';
legend = " ";
legendLength = strlen(legend);
@@ -172,8 +172,8 @@ void HistogramController::reloadBannerView() {
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
float size = m_store->heightOfBarAtIndex(*m_selectedBarIndex);
numberOfChar += Complex<float>::convertFloatToText(size, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
double size = m_store->heightOfBarAtIndex(*m_selectedBarIndex);
numberOfChar += Complex<double>::convertFloatToText(size, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);
@@ -185,8 +185,8 @@ void HistogramController::reloadBannerView() {
legendLength = strlen(legend);
strlcpy(buffer, legend, legendLength+1);
numberOfChar += legendLength;
float frequency = size/m_store->sumOfColumn(1);
numberOfChar += Complex<float>::convertFloatToText(frequency, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
double frequency = size/m_store->sumOfColumn(1);
numberOfChar += Complex<double>::convertFloatToText(frequency, buffer+numberOfChar, PrintFloat::bufferSizeForFloatsWithPrecision(Constant::LargeNumberOfSignificantDigits), Constant::LargeNumberOfSignificantDigits);
legend = " ";
legendLength = strlen(legend);
strlcpy(buffer+numberOfChar, legend, legendLength+1);

View File

@@ -32,7 +32,7 @@ void HistogramParameterController::willDisplayCellForIndex(HighlightCell * cell,
FloatParameterController::willDisplayCellForIndex(cell, index);
}
float HistogramParameterController::parameterAtIndex(int index) {
double HistogramParameterController::parameterAtIndex(int index) {
assert(index >= 0 && index < k_numberOfCells);
if (index == 0) {
return m_store->barWidth();
@@ -40,10 +40,10 @@ float HistogramParameterController::parameterAtIndex(int index) {
return m_store->firstDrawnBarAbscissa();
}
bool HistogramParameterController::setParameterAtIndex(int parameterIndex, float f) {
bool HistogramParameterController::setParameterAtIndex(int parameterIndex, double f) {
assert(parameterIndex >= 0 && parameterIndex < k_numberOfCells);
if (parameterIndex == 0) {
float newNumberOfBars = std::ceil((m_store->maxValue() - m_store->minValue())/f);
double newNumberOfBars = std::ceil((m_store->maxValue() - m_store->minValue())/f);
if (f <= 0.0f || newNumberOfBars > Store::k_maxNumberOfBars) {
app()->displayWarning(I18n::Message::ForbiddenValue);
return false;

View File

@@ -16,8 +16,8 @@ public:
private:
HighlightCell * reusableParameterCell(int index, int type) override;
int reusableParameterCellCount(int type) override;
float parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, float f) override;
double parameterAtIndex(int index) override;
bool setParameterAtIndex(int parameterIndex, double f) override;
View * loadView() override;
void unloadView(View * view) override;
char m_draftTextBuffer[MessageTableCellWithEditableText::k_bufferLength];

View File

@@ -11,7 +11,8 @@ HistogramView::HistogramView(Store * store, BannerView * bannerView) :
m_store(store),
m_labels{},
m_highlightedBarStart(NAN),
m_highlightedBarEnd(NAN)
m_highlightedBarEnd(NAN),
m_totalSize(NAN)
{
}
@@ -27,6 +28,7 @@ void HistogramView::reload() {
}
void HistogramView::drawRect(KDContext * ctx, KDRect rect) const {
m_totalSize = m_store->sumOfColumn(1);
ctx->fillRect(rect, KDColorWhite);
drawAxes(ctx, rect, Axis::Horizontal);
drawLabels(ctx, rect, Axis::Horizontal, false);
@@ -55,7 +57,7 @@ char * HistogramView::label(Axis axis, int index) const {
}
float HistogramView::evaluateModelWithParameter(Model * curve, float t) const {
return m_store->heightOfBarAtValue(t)/m_store->sumOfColumn(1);
return m_store->heightOfBarAtValue(t)/m_totalSize;
}
}

View File

@@ -21,6 +21,9 @@ private:
char m_labels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)];
float m_highlightedBarStart;
float m_highlightedBarEnd;
/* We memoize the total size to avoid recomputing it in double precision at
* every call to evaluateModelWithParameter() */
mutable float m_totalSize;
};
}

View File

@@ -91,12 +91,12 @@ bool Store::scrollToSelectedBarIndex(int index) {
/* Calculation */
float Store::sumOfOccurrences() {
double Store::sumOfOccurrences() {
return sumOfColumn(1);
}
float Store::maxValue() {
float max = -FLT_MAX;
double Store::maxValue() {
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];
@@ -105,8 +105,8 @@ float Store::maxValue() {
return max;
}
float Store::minValue() {
float min = FLT_MAX;
double Store::minValue() {
float 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];
@@ -115,38 +115,38 @@ float Store::minValue() {
return min;
}
float Store::range() {
double Store::range() {
return maxValue()-minValue();
}
float Store::mean() {
double Store::mean() {
return sum()/sumOfColumn(1);
}
float Store::variance() {
double Store::variance() {
float m = mean();
return squaredValueSum()/sumOfColumn(1) - m*m;
}
float Store::standardDeviation() {
double Store::standardDeviation() {
return std::sqrt(variance());
}
float Store::firstQuartile() {
double Store::firstQuartile() {
int firstQuartileIndex = std::ceil(sumOfColumn(1)/4);
return sortedElementNumber(firstQuartileIndex);
}
float Store::thirdQuartile() {
double Store::thirdQuartile() {
int thirdQuartileIndex = std::ceil(3*sumOfColumn(1)/4);
return sortedElementNumber(thirdQuartileIndex);
}
float Store::quartileRange() {
double Store::quartileRange() {
return thirdQuartile()-firstQuartile();
}
float Store::median() {
double Store::median() {
int total = sumOfColumn(1);
int halfTotal = total/2;
int totalMod2 = total - 2*halfTotal;
@@ -159,7 +159,7 @@ float Store::median() {
}
}
float Store::sum() {
double Store::sum() {
float result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[0][k]*m_data[1][k];
@@ -167,7 +167,7 @@ float Store::sum() {
return result;
}
float Store::squaredValueSum() {
double Store::squaredValueSum() {
float result = 0;
for (int k = 0; k < m_numberOfPairs; k++) {
result += m_data[0][k]*m_data[0][k]*m_data[1][k];
@@ -177,11 +177,11 @@ float Store::squaredValueSum() {
/* private methods */
float Store::defaultValue(int i) {
double Store::defaultValue(int i) {
if (i == 0) {
return 0.0f;
return 0.0;
}
return 1.0f;
return 1.0;
}
float Store::sumOfValuesBetween(float x1, float x2) {
@@ -194,21 +194,21 @@ float Store::sumOfValuesBetween(float x1, float x2) {
return result;
}
float Store::sortedElementNumber(int k) {
double Store::sortedElementNumber(int k) {
// TODO: use an other algorithm (ex quickselect) to avoid quadratic complexity
float bufferValues[m_numberOfPairs];
memcpy(bufferValues, m_data[0], m_numberOfPairs*sizeof(float));
double bufferValues[m_numberOfPairs];
memcpy(bufferValues, m_data[0], m_numberOfPairs*sizeof(double));
int sortedElementIndex = 0;
float cumulatedSize = 0.0f;
double cumulatedSize = 0.0;
while (cumulatedSize < k) {
sortedElementIndex = minIndex(bufferValues, m_numberOfPairs);
bufferValues[sortedElementIndex] = FLT_MAX;
bufferValues[sortedElementIndex] = DBL_MAX;
cumulatedSize += m_data[1][sortedElementIndex];
}
return m_data[0][sortedElementIndex];
}
int Store::minIndex(float * bufferValues, int bufferLength) {
int Store::minIndex(double * bufferValues, int bufferLength) {
int index = 0;
for (int i = 1; i < bufferLength; i++) {
if (bufferValues[index] > bufferValues[i]) {

View File

@@ -24,35 +24,35 @@ public:
bool scrollToSelectedBarIndex(int index);
// Calculation
float sumOfOccurrences();
float maxValue();
float minValue();
float range();
float mean();
float variance();
float standardDeviation();
float firstQuartile();
float thirdQuartile();
float quartileRange();
float median();
float sum();
float squaredValueSum();
double sumOfOccurrences();
double maxValue();
double minValue();
double range();
double mean();
double variance();
double standardDeviation();
double firstQuartile();
double thirdQuartile();
double quartileRange();
double median();
double sum();
double squaredValueSum();
constexpr static float k_maxNumberOfBars = 10000.0f;
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:
float defaultValue(int i) override;
double defaultValue(int i) override;
float sumOfValuesBetween(float x1, float x2);
float sortedElementNumber(int k);
int minIndex(float * bufferValues, int bufferLength);
double sortedElementNumber(int k);
int minIndex(double * bufferValues, int bufferLength);
// Histogram bars
float m_barWidth;
float m_firstDrawnBarAbscissa;
};
typedef float (Store::*CalculPointer)();
typedef double (Store::*CalculPointer)();
}

View File

@@ -33,7 +33,7 @@ HighlightCell * StoreController::titleCells(int index) {
return m_titleCells[index];
}
bool StoreController::setDataAtLocation(float floatBody, int columnIndex, int rowIndex) {
bool StoreController::setDataAtLocation(double floatBody, int columnIndex, int rowIndex) {
if (columnIndex == 1) {
if (floatBody < 0) {
return false;

View File

@@ -12,7 +12,7 @@ public:
StoreController(Responder * parentResponder, Store * store, ButtonRowController * header);
void willDisplayCellAtLocation(HighlightCell * cell, int i, int j) override;
private:
bool setDataAtLocation(float floatBody, int columnIndex, int rowIndex) override;
bool setDataAtLocation(double floatBody, int columnIndex, int rowIndex) override;
HighlightCell * titleCells(int index) override;
View * loadView() override;
void unloadView(View * view) override;