Numworks Epsilon  1.4.1
Graphing Calculator Operating System
store.cpp
Go to the documentation of this file.
1 #include "store.h"
2 #include <assert.h>
3 #include <float.h>
4 #include <cmath>
5 #include <string.h>
6 
7 using namespace Shared;
8 
9 namespace Regression {
10 
11 Store::Store() :
12  InteractiveCurveViewRange(nullptr, this),
14 {
15 }
16 
17 /* Dots */
18 
19 int Store::closestVerticalDot(int direction, float x) {
20  float nextX = INFINITY;
21  float nextY = INFINITY;
22  int selectedDot = -1;
23  /* The conditions to test on all dots are in this order:
24  * - the next dot should be within the window abscissa bounds
25  * - the next dot is the closest one in abscissa to x
26  * - the next dot is above the regression curve if direction == 1 and below
27  * otherwise */
28  for (int index = 0; index < m_numberOfPairs; index++) {
29  if ((m_xMin <= m_data[0][index] && m_data[0][index] <= m_xMax) &&
30  (std::fabs(m_data[0][index] - x) < std::fabs(nextX - x)) &&
31  ((m_data[1][index] - yValueForXValue(m_data[0][index]) >= 0) == (direction > 0))) {
32  // Handle edge case: if 2 dots have the same abscissa but different ordinates
33  if (nextX != m_data[0][index] || ((nextY - m_data[1][index] >= 0) == (direction > 0))) {
34  nextX = m_data[0][index];
35  nextY = m_data[1][index];
36  selectedDot = index;
37  }
38  }
39  }
40  // Compare with the mean dot
41  if (m_xMin <= meanOfColumn(0) && meanOfColumn(0) <= m_xMax &&
42  (std::fabs(meanOfColumn(0) - x) < std::fabs(nextX - x)) &&
43  ((meanOfColumn(1) - yValueForXValue(meanOfColumn(0)) >= 0) == (direction > 0))) {
44  if (nextX != meanOfColumn(0) || ((nextY - meanOfColumn(1) >= 0) == (direction > 0))) {
45  selectedDot = m_numberOfPairs;
46  }
47  }
48  return selectedDot;
49 }
50 
51 int Store::nextDot(int direction, int dot) {
52  float nextX = INFINITY;
53  int selectedDot = -1;
54  float x = meanOfColumn(0);
55  if (dot >= 0 && dot < m_numberOfPairs) {
56  x = get(0, dot);
57  }
58  /* We have to scan the Store in opposite ways for the 2 directions to ensure to
59  * select all dots (even with equal abscissa) */
60  if (direction > 0) {
61  for (int index = 0; index < m_numberOfPairs; index++) {
62  /* The conditions to test are in this order:
63  * - the next dot is the closest one in abscissa to x
64  * - the next dot is not the same as the selected one
65  * - the next dot is at the right of the selected one */
66  if (std::fabs(m_data[0][index] - x) < std::fabs(nextX - x) &&
67  (index != dot) &&
68  (m_data[0][index] >= x)) {
69  // Handle edge case: 2 dots have same abscissa
70  if (m_data[0][index] != x || (index > dot)) {
71  nextX = m_data[0][index];
72  selectedDot = index;
73  }
74  }
75  }
76  // Compare with the mean dot
77  if (std::fabs(meanOfColumn(0) - x) < std::fabs(nextX - x) &&
78  (m_numberOfPairs != dot) &&
79  (meanOfColumn(0) >= x)) {
80  if (meanOfColumn(0) != x || (x > dot)) {
81  selectedDot = m_numberOfPairs;
82  }
83  }
84  } else {
85  // Compare with the mean dot
86  if (std::fabs(meanOfColumn(0) - x) < std::fabs(nextX - x) &&
87  (m_numberOfPairs != dot) &&
88  (meanOfColumn(0) <= x)) {
89  if (meanOfColumn(0) != x || (m_numberOfPairs < dot)) {
90  nextX = meanOfColumn(0);
91  selectedDot = m_numberOfPairs;
92  }
93  }
94  for (int index = m_numberOfPairs-1; index >= 0; index--) {
95  if (std::fabs(m_data[0][index] - x) < std::fabs(nextX - x) &&
96  (index != dot) &&
97  (m_data[0][index] <= x)) {
98  // Handle edge case: 2 dots have same abscissa
99  if (m_data[0][index] != x || (index < dot)) {
100  nextX = m_data[0][index];
101  selectedDot = index;
102  }
103  }
104  }
105  }
106  return selectedDot;
107 }
108 
109 /* Window */
110 
112  float min = minValueOfColumn(0);
113  float max = maxValueOfColumn(0);
114  float range = max - min;
115  setXMin(min - k_displayLeftMarginRatio*range);
116  setXMax(max + k_displayRightMarginRatio*range);
117  setYAuto(true);
118 }
119 
120 /* Calculations */
121 
123  return m_numberOfPairs;
124 }
125 
126 float Store::maxValueOfColumn(int i) {
127  float max = -FLT_MAX;
128  for (int k = 0; k < m_numberOfPairs; k++) {
129  if (m_data[i][k] > max) {
130  max = m_data[i][k];
131  }
132  }
133  return max;
134 }
135 
136 float Store::minValueOfColumn(int i) {
137  float min = FLT_MAX;
138  for (int k = 0; k < m_numberOfPairs; k++) {
139  if (m_data[i][k] < min) {
140  min = m_data[i][k];
141  }
142  }
143  return min;
144 }
145 
147  double result = 0;
148  for (int k = 0; k < m_numberOfPairs; k++) {
149  result += m_data[i][k]*m_data[i][k];
150  }
151  return result;
152 }
153 
155  double result = 0;
156  for (int k = 0; k < m_numberOfPairs; k++) {
157  result += m_data[0][k]*m_data[1][k];
158  }
159  return result;
160 }
161 
162 double Store::meanOfColumn(int i) {
163  if (m_numberOfPairs == 0) {
164  return 0;
165  }
166  return sumOfColumn(i)/m_numberOfPairs;
167 }
168 
169 double Store::varianceOfColumn(int i) {
170  double mean = meanOfColumn(i);
171  return squaredValueSumOfColumn(i)/m_numberOfPairs - mean*mean;
172 }
173 
175  return std::sqrt(varianceOfColumn(i));
176 }
177 
180 }
181 
182 double Store::slope() {
183  return covariance()/varianceOfColumn(0);
184 }
185 
187  return meanOfColumn(1) - slope()*meanOfColumn(0);
188 }
189 
190 double Store::yValueForXValue(double x) {
191  return slope()*x+yIntercept();
192 }
193 
194 double Store::xValueForYValue(double y) {
195  if (std::fabs(slope()) < DBL_EPSILON) {
196  return NAN;
197  }
198  return (y - yIntercept())/slope();
199 }
200 
202  double sd0 = standardDeviationOfColumn(0);
203  double sd1 = standardDeviationOfColumn(1);
204  if (sd0 == 0.0 || sd1 == 0.0) {
205  return 1.0;
206  }
207  return covariance()/(sd0*sd1);
208 }
209 
211  double cov = covariance();
212  double v0 = varianceOfColumn(0);
213  double v1 = varianceOfColumn(1);
214  if (v0 == 0.0 || v1 == 0.0) {
215  return 1.0;
216  }
217  return cov*cov/(v0*v1);
218 }
219 
220 InteractiveCurveViewRangeDelegate::Range Store::computeYRange(InteractiveCurveViewRange * interactiveCurveViewRange) {
221  float min = FLT_MAX;
222  float max = -FLT_MAX;
223  for (int k = 0; k < m_numberOfPairs; k++) {
224  if (m_xMin <= m_data[0][k] && m_data[0][k] <= m_xMax) {
225  if (m_data[1][k] < min) {
226  min = m_data[1][k];
227  }
228  if (m_data[1][k] > max) {
229  max = m_data[1][k];
230  }
231  }
232  }
234  range.min = min;
235  range.max = max;
236  return range;
237 }
238 
239 float Store::addMargin(float x, float range, bool isMin) {
240  float ratio = isMin ? -k_displayBottomMarginRatio : k_displayTopMarginRatio;
241  return x+ratio*range;
242 }
243 
244 }
double squaredCorrelationCoefficient()
Definition: store.cpp:210
#define NAN
Definition: math.h:30
double columnProductSum()
Definition: store.cpp:154
double standardDeviationOfColumn(int i)
Definition: store.cpp:174
int closestVerticalDot(int direction, float x)
Definition: store.cpp:19
double meanOfColumn(int i)
Definition: store.cpp:162
double correlationCoefficient()
Definition: store.cpp:201
#define fabs(x)
Definition: math.h:178
double varianceOfColumn(int i)
Definition: store.cpp:169
int nextDot(int direction, int dot)
Definition: store.cpp:51
#define DBL_EPSILON
Definition: float.h:11
#define FLT_MAX
Definition: float.h:6
double yIntercept()
Definition: store.cpp:186
double m_data[2][k_maxNumberOfPairs]
#define INFINITY
Definition: math.h:29
double xValueForYValue(double y)
Definition: store.cpp:194
void setDefault() override
Definition: store.cpp:111
double squaredValueSumOfColumn(int i)
Definition: store.cpp:146
double yValueForXValue(double x)
Definition: store.cpp:190
double numberOfPairs()
Definition: store.cpp:122
double slope()
Definition: store.cpp:182
#define sqrt(x)
Definition: math.h:196
double covariance()
Definition: store.cpp:178