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
39namespace Calligra
40{
41namespace Sheets
42{
43class Cell;
44class Doc;
45class ValueCalc;
46class ValueConverter;
47
48// Condition structures
49enum Comp { isEqual, isLess, isGreater, lessEqual, greaterEqual, notEqual, stringMatch, regexMatch, wildcardMatch };
50enum Type { numeric, string };
51
52struct Condition {
53 Comp comp;
54 int index;
55 Number value;
56 QString stringValue;
57 Type type;
58};
59
60typedef void (*arrayWalkFunc)(ValueCalc *, Value &result,
61 Value val, Value param);
62// A function that can map an array element-wise
63typedef Value (ValueCalc::*arrayMapFunc)(const Value &val, const Value &param);
64
65/**
66 * \ingroup Value
67The ValueCalc class is used to perform all sorts of calculations.
68
69Usage of this class for simpler calculations is deprecated, as we now use
70the Number object directly for that. This class is to be used for computations
71of more complicated and ranged functions.
72*/
73
74class CALLIGRA_SHEETS_ODF_EXPORT ValueCalc
75{
76public:
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 &param);
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
332protected:
333 ValueConverter* converter;
334
335 /** registered array-walk functions */
336 std::map<QString, arrayWalkFunc> awFuncs;
337};
338
339inline 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
348inline 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