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 ¶m);
/**
* \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 ¶m);
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
|