1 | /* This file is part of the KDE project |
2 | Copyright (C) 2005-2007 Tomas Mecir <mecirt@gmail.com> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #ifndef CALLIGRA_SHEETS_VALUECALC |
21 | #define CALLIGRA_SHEETS_VALUECALC |
22 | |
23 | #include <map> |
24 | |
25 | #include <QVector> |
26 | |
27 | #include "Number.h" |
28 | #include "Value.h" |
29 | |
30 | #include "calligra_sheets_export.h" |
31 | |
32 | #ifdef max |
33 | # undef max |
34 | #endif |
35 | #ifdef min |
36 | # undef min |
37 | #endif |
38 | |
39 | namespace Calligra |
40 | { |
41 | namespace Sheets |
42 | { |
43 | class Cell; |
44 | class Doc; |
45 | class ValueCalc; |
46 | class ValueConverter; |
47 | |
48 | // Condition structures |
49 | enum Comp { isEqual, isLess, isGreater, lessEqual, greaterEqual, notEqual, stringMatch, regexMatch, wildcardMatch }; |
50 | enum Type { numeric, string }; |
51 | |
52 | struct Condition { |
53 | Comp comp; |
54 | int index; |
55 | Number value; |
56 | QString stringValue; |
57 | Type type; |
58 | }; |
59 | |
60 | typedef void (*arrayWalkFunc)(ValueCalc *, Value &result, |
61 | Value val, Value param); |
62 | // A function that can map an array element-wise |
63 | typedef Value (ValueCalc::*arrayMapFunc)(const Value &val, const Value ¶m); |
64 | |
65 | /** |
66 | * \ingroup Value |
67 | The ValueCalc class is used to perform all sorts of calculations. |
68 | |
69 | Usage of this class for simpler calculations is deprecated, as we now use |
70 | the Number object directly for that. This class is to be used for computations |
71 | of more complicated and ranged functions. |
72 | */ |
73 | |
74 | class CALLIGRA_SHEETS_ODF_EXPORT ValueCalc |
75 | { |
76 | public: |
77 | explicit ValueCalc(ValueConverter* c); |
78 | |
79 | ValueConverter *conv() { |
80 | return converter; |
81 | } |
82 | |
83 | const CalculationSettings* settings() const; |
84 | |
85 | /** basic arithmetic operations */ |
86 | Value add(const Value &a, const Value &b); |
87 | Value sub(const Value &a, const Value &b); |
88 | Value mul(const Value &a, const Value &b); |
89 | Value div(const Value &a, const Value &b); |
90 | Value mod(const Value &a, const Value &b); |
91 | Value pow(const Value &a, const Value &b); |
92 | Value sqr(const Value &a); |
93 | Value sqrt(const Value &a); |
94 | Value add(const Value &a, Number b); |
95 | Value sub(const Value &a, Number b); |
96 | Value mul(const Value &a, Number b); |
97 | Value div(const Value &a, Number b); |
98 | Value pow(const Value &a, Number b); |
99 | Value abs(const Value &a); |
100 | |
101 | /** comparison and related */ |
102 | bool isZero(const Value &a); |
103 | bool isEven(const Value &a); |
104 | /** numerical comparison */ |
105 | bool equal(const Value &a, const Value &b); |
106 | /** numerical comparison with a little epsilon tolerance */ |
107 | bool approxEqual(const Value &a, const Value &b); |
108 | /** numerical comparison */ |
109 | bool greater(const Value &a, const Value &b); |
110 | /** numerical comparison - greater or equal */ |
111 | bool gequal(const Value &a, const Value &b); |
112 | /** numerical comparison */ |
113 | bool lower(const Value &a, const Value &b); |
114 | /** string comparison */ |
115 | bool strEqual(const Value &a, const Value &b, bool CalcS = true); |
116 | /** string comparison */ |
117 | bool strGreater(const Value &a, const Value &b, bool CalcS = true); |
118 | /** string comparison - greater or equal */ |
119 | bool strGequal(const Value &a, const Value &b, bool CalcS = true); |
120 | /** string comparison */ |
121 | bool strLower(const Value &a, const Value &b, bool CalcS = true); |
122 | /** string or numerical comparison */ |
123 | bool naturalEqual(const Value &a, const Value &b, bool CalcS = true); |
124 | /** string or numerical comparison */ |
125 | bool naturalGreater(const Value &a, const Value &b, bool CalcS = true); |
126 | /** string or numerical comparison - greater or equal */ |
127 | bool naturalGequal(const Value &a, const Value &b, bool CalcS = true); |
128 | /** string or numerical comparison */ |
129 | bool naturalLower(const Value &a, const Value &b, bool CalcS = true); |
130 | /** string or numerical comparison - lower or equal */ |
131 | bool naturalLequal(const Value &a, const Value &b, bool CalcS = true); |
132 | |
133 | int sign(const Value &a); |
134 | |
135 | // just a quick workaround |
136 | Value add(Number a, const Value& b) { |
137 | return add(Value(a), b); |
138 | } |
139 | Value sub(Number a, const Value& b) { |
140 | return sub(Value(a), b); |
141 | } |
142 | Value mul(Number a, const Value& b) { |
143 | return mul(Value(a), b); |
144 | } |
145 | Value div(Number a, const Value& b) { |
146 | return div(Value(a), b); |
147 | } |
148 | Value pow(Number a, const Value& b) { |
149 | return pow(Value(a), b); |
150 | } |
151 | |
152 | bool equal(const Value &a, Number b) { |
153 | return equal(a, Value(b)); |
154 | } |
155 | bool greater(const Value &a, Number b) { |
156 | return greater(a, Value(b)); |
157 | } |
158 | bool lower(const Value &a, Number b) { |
159 | return lower(a, Value(b)); |
160 | } |
161 | bool equal(Number a, const Value &b) { |
162 | return equal(Value(a), b); |
163 | } |
164 | bool greater(Number a, const Value &b) { |
165 | return greater(Value(a), b); |
166 | } |
167 | bool lower(Number a, const Value &b) { |
168 | return lower(Value(a), b); |
169 | } |
170 | |
171 | |
172 | /** rounding */ |
173 | Value roundDown(const Value &a, const Value &digits); |
174 | Value roundUp(const Value &a, const Value &digits); |
175 | Value round(const Value &a, const Value &digits); |
176 | Value roundDown(const Value &a, int digits = 0); |
177 | Value roundUp(const Value &a, int digits = 0); |
178 | Value round(const Value &a, int digits = 0); |
179 | |
180 | /** logarithms and exponentials */ |
181 | Value log(const Value &number, const Value &base); |
182 | Value log(const Value &number, Number base = 10); |
183 | Value ln(const Value &number); |
184 | Value exp(const Value &number); |
185 | |
186 | /** constants */ |
187 | Value pi(); |
188 | Value eps(); |
189 | |
190 | /** random number from <0.0, range) */ |
191 | Value random(Number range = 1.0); |
192 | Value random(Value range); |
193 | |
194 | /** some computational functions */ |
195 | Value fact(const Value &which); |
196 | Value fact(const Value &which, const Value &end); |
197 | Value fact(int which, int end = 0); |
198 | /** Number factorial (every other number multiplied) */ |
199 | Value factDouble(int which); |
200 | Value factDouble(Value which); |
201 | |
202 | /** combinations */ |
203 | Value combin(int n, int k); |
204 | Value combin(Value n, Value k); |
205 | |
206 | /** greatest common divisor */ |
207 | Value gcd(const Value &a, const Value &b); |
208 | /** lowest common multiplicator */ |
209 | Value lcm(const Value &a, const Value &b); |
210 | |
211 | /** base conversion 10 -> base */ |
212 | Value base(const Value &val, int base = 16, int prec = 0, int minLength = 0); |
213 | /** base conversion base -> 10 */ |
214 | Value fromBase(const Value &val, int base = 16); |
215 | |
216 | /** goniometric functions */ |
217 | Value sin(const Value &number); |
218 | Value cos(const Value &number); |
219 | Value tg(const Value &number); |
220 | Value cotg(const Value &number); |
221 | Value asin(const Value &number); |
222 | Value acos(const Value &number); |
223 | Value atg(const Value &number); |
224 | Value atan2(const Value &y, const Value &x); |
225 | |
226 | /** hyperbolic functions */ |
227 | Value sinh(const Value &number); |
228 | Value cosh(const Value &number); |
229 | Value tgh(const Value &number); |
230 | Value asinh(const Value &number); |
231 | Value acosh(const Value &number); |
232 | Value atgh(const Value &number); |
233 | |
234 | /** some statistical stuff |
235 | TODO: we may want to move these over to a separate class or something, |
236 | as the functions are mostly big */ |
237 | Value phi(Value x); |
238 | Value gauss(Value xx); |
239 | Value gaussinv(Value xx); |
240 | Value GetGamma(Value _x); |
241 | Value GetLogGamma(Value _x); |
242 | Value GetGammaDist(Value _x, Value _alpha, |
243 | Value _beta); |
244 | Value GetBeta(Value _x, Value _alpha, |
245 | Value _beta); |
246 | |
247 | /** bessel functions - may also end up being separated from here */ |
248 | Value besseli(Value v, Value x); |
249 | Value besselj(Value v, Value x); |
250 | Value besselk(Value v, Value x); |
251 | Value besseln(Value v, Value x); |
252 | |
253 | /** error functions (see: man erf) */ |
254 | Value erf(Value x); |
255 | Value erfc(Value x); |
256 | |
257 | /** array/range walking */ |
258 | void arrayWalk(const Value &range, Value &res, |
259 | arrayWalkFunc func, Value param); |
260 | /** Walk the array in function-like style. |
261 | This method is here to avoid duplication in function handlers. */ |
262 | void arrayWalk(QVector<Value> &range, Value &res, |
263 | arrayWalkFunc func, Value param); |
264 | Value arrayMap(const Value &array, arrayMapFunc func, const Value ¶m); |
265 | Value twoArrayMap(const Value &array1, arrayMapFunc func, const Value &array2); |
266 | void twoArrayWalk(const Value &a1, const Value &a2, |
267 | Value &res, arrayWalkFunc func); |
268 | void twoArrayWalk(QVector<Value> &a1, |
269 | QVector<Value> &a2, Value &res, arrayWalkFunc func); |
270 | arrayWalkFunc awFunc(const QString &name); |
271 | void registerAwFunc(const QString &name, arrayWalkFunc func); |
272 | |
273 | /** basic range functions */ |
274 | // if full is true, A-version is used (means string/bool values included) |
275 | Value sum(const Value &range, bool full = true); |
276 | Value sumsq(const Value &range, bool full = true); |
277 | Value sumIf(const Value &range, const Condition &cond); |
278 | Value sumIf(const Cell &sumRangeStart, |
279 | const Value &checkRange, const Condition &cond); |
280 | Value sumIfs(const Cell &sumRangeStart, |
281 | QList<Value> c_Range, QList<Condition> cond, const float limit); |
282 | Value averageIf(const Value &range, const Condition &cond); |
283 | Value averageIf(const Cell &avgRangeStart, |
284 | const Value &checkRange, const Condition &cond); |
285 | Value averageIfs(const Cell &avgRangeStart, |
286 | QList<Value> c_Range, QList<Condition> cond, const float limit); |
287 | int count(const Value &range, bool full = true); |
288 | int countIf(const Value &range, const Condition &cond); |
289 | Value countIfs(const Cell &cntRangeStart, QList<Value> c_range, QList<Condition> cond, const float limit); |
290 | Value avg(const Value &range, bool full = true); |
291 | Value max(const Value &range, bool full = true); |
292 | Value min(const Value &range, bool full = true); |
293 | Value product(const Value &range, Value init, |
294 | bool full = true); |
295 | Value stddev(const Value &range, bool full = true); |
296 | Value stddev(const Value &range, Value avg, |
297 | bool full = true); |
298 | Value stddevP(const Value &range, bool full = true); |
299 | Value stddevP(const Value &range, Value avg, |
300 | bool full = true); |
301 | |
302 | /** range functions using value lists */ |
303 | Value sum(QVector<Value> range, bool full = true); |
304 | int count(QVector<Value> range, bool full = true); |
305 | Value avg(QVector<Value> range, bool full = true); |
306 | Value max(QVector<Value> range, bool full = true); |
307 | Value min(QVector<Value> range, bool full = true); |
308 | Value product(QVector<Value> range, Value init, |
309 | bool full = true); |
310 | Value stddev(QVector<Value> range, bool full = true); |
311 | Value stddev(QVector<Value> range, Value avg, |
312 | bool full = true); |
313 | Value stddevP(QVector<Value> range, bool full = true); |
314 | Value stddevP(QVector<Value> range, Value avg, |
315 | bool full = true); |
316 | |
317 | /** |
318 | This method parses the condition in string text to the condition cond. |
319 | It sets the condition's type and value. |
320 | */ |
321 | void getCond(Condition &cond, Value val); |
322 | |
323 | /** |
324 | Returns true if value d matches the condition cond, built with getCond(). |
325 | Otherwise, it returns false. |
326 | */ |
327 | bool matches(const Condition &cond, Value d); |
328 | |
329 | /** return formatting for the result, based on formattings of input values */ |
330 | Value::Format format(Value a, Value b); |
331 | |
332 | protected: |
333 | ValueConverter* converter; |
334 | |
335 | /** registered array-walk functions */ |
336 | std::map<QString, arrayWalkFunc> awFuncs; |
337 | }; |
338 | |
339 | inline bool approxEqual(double a, double b) |
340 | { |
341 | if (a == b) |
342 | return true; |
343 | double x = a - b; |
344 | return (x < 0.0 ? -x : x) |
345 | < ((a < 0.0 ? -a : a) *(1.0 / (16777216.0 * 16777216.0))); |
346 | } |
347 | |
348 | inline double approxFloor(double a) |
349 | { |
350 | double b = floor(a); |
351 | // The second approxEqual() is necessary for values that are near the limit |
352 | // of numbers representable with 4 bits stripped off. (#i12446#) |
353 | if (approxEqual(a - 1.0, b) && !approxEqual(a, b)) |
354 | return b + 1.0; |
355 | return b; |
356 | } |
357 | |
358 | } // namespace Sheets |
359 | } // namespace Calligra |
360 | |
361 | |
362 | #endif // CALLIGRA_SHEETS_VALUECALC |
363 | |
364 | |