File: ValueCalc.h

package info (click to toggle)
calligra 1%3A3.2.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 260,432 kB
  • sloc: cpp: 650,911; xml: 27,662; python: 6,044; perl: 2,724; yacc: 1,817; ansic: 1,325; sh: 1,277; lex: 1,107; ruby: 1,010; javascript: 495; makefile: 24
file content (362 lines) | stat: -rw-r--r-- 12,680 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/* This file is part of the KDE project
   Copyright (C) 2005-2007 Tomas Mecir <mecirt@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#ifndef CALLIGRA_SHEETS_VALUECALC
#define CALLIGRA_SHEETS_VALUECALC

#include <map>

#include <QVector>

#include "Number.h"
#include "Value.h"

#include "sheets_odf_export.h"

#ifdef max
# undef max
#endif
#ifdef min
# undef min
#endif

namespace Calligra
{
namespace Sheets
{
class Cell;
class ValueCalc;
class ValueConverter;

// Condition structures
enum Comp { isEqual, isLess, isGreater, lessEqual, greaterEqual, notEqual, stringMatch, regexMatch, wildcardMatch };
enum Type { numeric, string };

struct Condition {
    Comp     comp;
    int      index;
    Number   value;
    QString  stringValue;
    Type     type;
};

typedef void (*arrayWalkFunc)(ValueCalc *, Value &result,
                              Value val, Value param);
// A function that can map an array element-wise
typedef Value (ValueCalc::*arrayMapFunc)(const Value &val, const Value &param);

/**
 * \ingroup Value
The ValueCalc class is used to perform all sorts of calculations.

Usage of this class for simpler calculations is deprecated, as we now use
the Number object directly for that. This class is to be used for computations
of more complicated and ranged functions.
*/

class CALLIGRA_SHEETS_ODF_EXPORT ValueCalc
{
public:
    explicit ValueCalc(ValueConverter* c);

    ValueConverter *conv() {
        return converter;
    }

    const CalculationSettings* settings() const;

    /** basic arithmetic operations */
    Value add(const Value &a, const Value &b);
    Value sub(const Value &a, const Value &b);
    Value mul(const Value &a, const Value &b);
    Value div(const Value &a, const Value &b);
    Value mod(const Value &a, const Value &b);
    Value pow(const Value &a, const Value &b);
    Value sqr(const Value &a);
    Value sqrt(const Value &a);
    Value add(const Value &a, Number b);
    Value sub(const Value &a, Number b);
    Value mul(const Value &a, Number b);
    Value div(const Value &a, Number b);
    Value pow(const Value &a, Number b);
    Value abs(const Value &a);

    /** comparison and related */
    bool isZero(const Value &a);
    bool isEven(const Value &a);
    /** numerical comparison */
    bool equal(const Value &a, const Value &b);
    /** numerical comparison with a little epsilon tolerance */
    bool approxEqual(const Value &a, const Value &b);
    /** numerical comparison */
    bool greater(const Value &a, const Value &b);
    /** numerical comparison - greater or equal */
    bool gequal(const Value &a, const Value &b);
    /** numerical comparison */
    bool lower(const Value &a, const Value &b);
    /** string comparison */
    bool strEqual(const Value &a, const Value &b, bool CalcS = true);
    /** string comparison */
    bool strGreater(const Value &a, const Value &b, bool CalcS = true);
    /** string comparison - greater or equal */
    bool strGequal(const Value &a, const Value &b, bool CalcS = true);
    /** string comparison */
    bool strLower(const Value &a, const Value &b, bool CalcS = true);
    /** string or numerical comparison */
    bool naturalEqual(const Value &a, const Value &b, bool CalcS = true);
    /** string or numerical comparison */
    bool naturalGreater(const Value &a, const Value &b, bool CalcS = true);
    /** string or numerical comparison - greater or equal */
    bool naturalGequal(const Value &a, const Value &b, bool CalcS = true);
    /** string or numerical comparison */
    bool naturalLower(const Value &a, const Value &b, bool CalcS = true);
    /** string or numerical comparison - lower or equal */
    bool naturalLequal(const Value &a, const Value &b, bool CalcS = true);

    int sign(const Value &a);

    // just a quick workaround
    Value add(Number a, const Value& b) {
        return add(Value(a), b);
    }
    Value sub(Number a, const Value& b) {
        return sub(Value(a), b);
    }
    Value mul(Number a, const Value& b) {
        return mul(Value(a), b);
    }
    Value div(Number a, const Value& b) {
        return div(Value(a), b);
    }
    Value pow(Number a, const Value& b) {
        return pow(Value(a), b);
    }

    bool equal(const Value &a, Number b)   {
        return equal(a, Value(b));
    }
    bool greater(const Value &a, Number b) {
        return greater(a, Value(b));
    }
    bool lower(const Value &a, Number b)   {
        return lower(a, Value(b));
    }
    bool equal(Number a, const Value &b)   {
        return equal(Value(a), b);
    }
    bool greater(Number a, const Value &b) {
        return greater(Value(a), b);
    }
    bool lower(Number a, const Value &b)   {
        return lower(Value(a), b);
    }


    /** rounding */
    Value roundDown(const Value &a, const Value &digits);
    Value roundUp(const Value &a, const Value &digits);
    Value round(const Value &a, const Value &digits);
    Value roundDown(const Value &a, int digits = 0);
    Value roundUp(const Value &a, int digits = 0);
    Value round(const Value &a, int digits = 0);

    /** logarithms and exponentials */
    Value log(const Value &number, const Value &base);
    Value log(const Value &number, Number base = 10);
    Value ln(const Value &number);
    Value exp(const Value &number);

    /** constants */
    Value pi();
    Value eps();

    /** random number from <0.0, range) */
    Value random(Number range = 1.0);
    Value random(Value range);

    /** some computational functions */
    Value fact(const Value &which);
    Value fact(const Value &which, const Value &end);
    Value fact(int which, int end = 0);
    /** Number factorial (every other number multiplied) */
    Value factDouble(int which);
    Value factDouble(Value which);

    /** combinations */
    Value combin(int n, int k);
    Value combin(Value n, Value k);

    /** greatest common divisor */
    Value gcd(const Value &a, const Value &b);
    /** lowest common multiplicator */
    Value lcm(const Value &a, const Value &b);

    /** base conversion 10 -> base */
    Value base(const Value &val, int base = 16, int prec = 0, int minLength = 0);
    /** base conversion base -> 10 */
    Value fromBase(const Value &val, int base = 16);

    /** goniometric functions */
    Value sin(const Value &number);
    Value cos(const Value &number);
    Value tg(const Value &number);
    Value cotg(const Value &number);
    Value asin(const Value &number);
    Value acos(const Value &number);
    Value atg(const Value &number);
    Value atan2(const Value &y, const Value &x);

    /** hyperbolic functions */
    Value sinh(const Value &number);
    Value cosh(const Value &number);
    Value tgh(const Value &number);
    Value asinh(const Value &number);
    Value acosh(const Value &number);
    Value atgh(const Value &number);

    /** some statistical stuff
      TODO: we may want to move these over to a separate class or something,
      as the functions are mostly big */
    Value phi(Value x);
    Value gauss(Value xx);
    Value gaussinv(Value xx);
    Value GetGamma(Value _x);
    Value GetLogGamma(Value _x);
    Value GetGammaDist(Value _x, Value _alpha,
                       Value _beta);
    Value GetBeta(Value _x, Value _alpha,
                  Value _beta);

    /** bessel functions - may also end up being separated from here */
    Value besseli(Value v, Value x);
    Value besselj(Value v, Value x);
    Value besselk(Value v, Value x);
    Value besseln(Value v, Value x);

    /** error functions (see: man erf) */
    Value erf(Value x);
    Value erfc(Value x);

    /** array/range walking */
    void arrayWalk(const Value &range, Value &res,
                   arrayWalkFunc func, Value param);
    /** Walk the array in function-like style.
    This method is here to avoid duplication in function handlers. */
    void arrayWalk(QVector<Value> &range, Value &res,
                   arrayWalkFunc func, Value param);
    Value arrayMap(const Value &array, arrayMapFunc func, const Value &param);
    Value twoArrayMap(const Value &array1, arrayMapFunc func, const Value &array2);
    void twoArrayWalk(const Value &a1, const Value &a2,
                      Value &res, arrayWalkFunc func);
    void twoArrayWalk(QVector<Value> &a1,
                      QVector<Value> &a2, Value &res, arrayWalkFunc func);
    arrayWalkFunc awFunc(const QString &name);
    void registerAwFunc(const QString &name, arrayWalkFunc func);

    /** basic range functions */
    // if full is true, A-version is used (means string/bool values included)
    Value sum(const Value &range, bool full = true);
    Value sumsq(const Value &range, bool full = true);
    Value sumIf(const Value &range, const Condition &cond);
    Value sumIf(const Cell &sumRangeStart,
                const Value &checkRange, const Condition &cond);
    Value sumIfs(const Cell &sumRangeStart,
                 QList<Value> c_Range, QList<Condition> cond, const float limit);
    Value averageIf(const Value &range, const Condition &cond);
    Value averageIf(const Cell &avgRangeStart,
                const Value &checkRange, const Condition &cond);
    Value averageIfs(const Cell &avgRangeStart,
                 QList<Value> c_Range, QList<Condition> cond, const float limit);
    int count(const Value &range, bool full = true);
    int countIf(const Value &range, const Condition &cond);
    Value countIfs(const Cell &cntRangeStart, QList<Value> c_range, QList<Condition> cond, const float limit);
    Value avg(const Value &range, bool full = true);
    Value max(const Value &range, bool full = true);
    Value min(const Value &range, bool full = true);
    Value product(const Value &range, Value init,
                  bool full = true);
    Value stddev(const Value &range, bool full = true);
    Value stddev(const Value &range, Value avg,
                 bool full = true);
    Value stddevP(const Value &range, bool full = true);
    Value stddevP(const Value &range, Value avg,
                  bool full = true);

    /** range functions using value lists */
    Value sum(QVector<Value> range, bool full = true);
    int count(QVector<Value> range, bool full = true);
    Value avg(QVector<Value> range, bool full = true);
    Value max(QVector<Value> range, bool full = true);
    Value min(QVector<Value> range, bool full = true);
    Value product(QVector<Value> range, Value init,
                  bool full = true);
    Value stddev(QVector<Value> range, bool full = true);
    Value stddev(QVector<Value> range, Value avg,
                 bool full = true);
    Value stddevP(QVector<Value> range, bool full = true);
    Value stddevP(QVector<Value> range, Value avg,
                  bool full = true);

    /**
      This method parses the condition in string text to the condition cond.
      It sets the condition's type and value.
    */
    void getCond(Condition &cond, Value val);

    /**
      Returns true if value d matches the condition cond, built with getCond().
      Otherwise, it returns false.
    */
    bool matches(const Condition &cond, Value d);

    /** return formatting for the result, based on formattings of input values */
    Value::Format format(Value a, Value b);

protected:
    ValueConverter* converter;

    /** registered array-walk functions */
    std::map<QString, arrayWalkFunc> awFuncs;
};

inline bool approxEqual(double a, double b)
{
    if (a == b)
        return true;
    double x = a - b;
    return (x < 0.0 ? -x : x)
           < ((a < 0.0 ? -a : a) *(1.0 / (16777216.0 * 16777216.0)));
}

inline double approxFloor(double a)
{
    double b = floor(a);
    // The second approxEqual() is necessary for values that are near the limit
    // of numbers representable with 4 bits stripped off. (#i12446#)
    if (approxEqual(a - 1.0, b) && !approxEqual(a, b))
        return b + 1.0;
    return b;
}

} // namespace Sheets
} // namespace Calligra


#endif // CALLIGRA_SHEETS_VALUECALC