mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-19 00:37:25 +01:00
[apps] Operations in double when precision required
Change-Id: I7168a861a76178f0bf81841e9378f7399f67914a
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)();
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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)();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user