File indexing completed on 2024-04-28 16:21:38

0001 /* This file is part of the KDE project
0002    Copyright (C) 2005-2007 Tomas Mecir <mecirt@gmail.com>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #ifndef CALLIGRA_SHEETS_VALUECALC
0021 #define CALLIGRA_SHEETS_VALUECALC
0022 
0023 #include <map>
0024 
0025 #include <QVector>
0026 
0027 #include "Number.h"
0028 #include "Value.h"
0029 
0030 #include "sheets_odf_export.h"
0031 
0032 #ifdef max
0033 # undef max
0034 #endif
0035 #ifdef min
0036 # undef min
0037 #endif
0038 
0039 namespace Calligra
0040 {
0041 namespace Sheets
0042 {
0043 class Cell;
0044 class ValueCalc;
0045 class ValueConverter;
0046 
0047 // Condition structures
0048 enum Comp { isEqual, isLess, isGreater, lessEqual, greaterEqual, notEqual, stringMatch, regexMatch, wildcardMatch };
0049 enum Type { numeric, string };
0050 
0051 struct Condition {
0052     Comp     comp;
0053     int      index;
0054     Number   value;
0055     QString  stringValue;
0056     Type     type;
0057 };
0058 
0059 typedef void (*arrayWalkFunc)(ValueCalc *, Value &result,
0060                               Value val, Value param);
0061 // A function that can map an array element-wise
0062 typedef Value (ValueCalc::*arrayMapFunc)(const Value &val, const Value &param);
0063 
0064 /**
0065  * \ingroup Value
0066 The ValueCalc class is used to perform all sorts of calculations.
0067 
0068 Usage of this class for simpler calculations is deprecated, as we now use
0069 the Number object directly for that. This class is to be used for computations
0070 of more complicated and ranged functions.
0071 */
0072 
0073 class CALLIGRA_SHEETS_ODF_EXPORT ValueCalc
0074 {
0075 public:
0076     explicit ValueCalc(ValueConverter* c);
0077 
0078     ValueConverter *conv() {
0079         return converter;
0080     }
0081 
0082     const CalculationSettings* settings() const;
0083 
0084     /** basic arithmetic operations */
0085     Value add(const Value &a, const Value &b);
0086     Value sub(const Value &a, const Value &b);
0087     Value mul(const Value &a, const Value &b);
0088     Value div(const Value &a, const Value &b);
0089     Value mod(const Value &a, const Value &b);
0090     Value pow(const Value &a, const Value &b);
0091     Value sqr(const Value &a);
0092     Value sqrt(const Value &a);
0093     Value add(const Value &a, Number b);
0094     Value sub(const Value &a, Number b);
0095     Value mul(const Value &a, Number b);
0096     Value div(const Value &a, Number b);
0097     Value pow(const Value &a, Number b);
0098     Value abs(const Value &a);
0099 
0100     /** comparison and related */
0101     bool isZero(const Value &a);
0102     bool isEven(const Value &a);
0103     /** numerical comparison */
0104     bool equal(const Value &a, const Value &b);
0105     /** numerical comparison with a little epsilon tolerance */
0106     bool approxEqual(const Value &a, const Value &b);
0107     /** numerical comparison */
0108     bool greater(const Value &a, const Value &b);
0109     /** numerical comparison - greater or equal */
0110     bool gequal(const Value &a, const Value &b);
0111     /** numerical comparison */
0112     bool lower(const Value &a, const Value &b);
0113     /** string comparison */
0114     bool strEqual(const Value &a, const Value &b, bool CalcS = true);
0115     /** string comparison */
0116     bool strGreater(const Value &a, const Value &b, bool CalcS = true);
0117     /** string comparison - greater or equal */
0118     bool strGequal(const Value &a, const Value &b, bool CalcS = true);
0119     /** string comparison */
0120     bool strLower(const Value &a, const Value &b, bool CalcS = true);
0121     /** string or numerical comparison */
0122     bool naturalEqual(const Value &a, const Value &b, bool CalcS = true);
0123     /** string or numerical comparison */
0124     bool naturalGreater(const Value &a, const Value &b, bool CalcS = true);
0125     /** string or numerical comparison - greater or equal */
0126     bool naturalGequal(const Value &a, const Value &b, bool CalcS = true);
0127     /** string or numerical comparison */
0128     bool naturalLower(const Value &a, const Value &b, bool CalcS = true);
0129     /** string or numerical comparison - lower or equal */
0130     bool naturalLequal(const Value &a, const Value &b, bool CalcS = true);
0131 
0132     int sign(const Value &a);
0133 
0134     // just a quick workaround
0135     Value add(Number a, const Value& b) {
0136         return add(Value(a), b);
0137     }
0138     Value sub(Number a, const Value& b) {
0139         return sub(Value(a), b);
0140     }
0141     Value mul(Number a, const Value& b) {
0142         return mul(Value(a), b);
0143     }
0144     Value div(Number a, const Value& b) {
0145         return div(Value(a), b);
0146     }
0147     Value pow(Number a, const Value& b) {
0148         return pow(Value(a), b);
0149     }
0150 
0151     bool equal(const Value &a, Number b)   {
0152         return equal(a, Value(b));
0153     }
0154     bool greater(const Value &a, Number b) {
0155         return greater(a, Value(b));
0156     }
0157     bool lower(const Value &a, Number b)   {
0158         return lower(a, Value(b));
0159     }
0160     bool equal(Number a, const Value &b)   {
0161         return equal(Value(a), b);
0162     }
0163     bool greater(Number a, const Value &b) {
0164         return greater(Value(a), b);
0165     }
0166     bool lower(Number a, const Value &b)   {
0167         return lower(Value(a), b);
0168     }
0169 
0170 
0171     /** rounding */
0172     Value roundDown(const Value &a, const Value &digits);
0173     Value roundUp(const Value &a, const Value &digits);
0174     Value round(const Value &a, const Value &digits);
0175     Value roundDown(const Value &a, int digits = 0);
0176     Value roundUp(const Value &a, int digits = 0);
0177     Value round(const Value &a, int digits = 0);
0178 
0179     /** logarithms and exponentials */
0180     Value log(const Value &number, const Value &base);
0181     Value log(const Value &number, Number base = 10);
0182     Value ln(const Value &number);
0183     Value exp(const Value &number);
0184 
0185     /** constants */
0186     Value pi();
0187     Value eps();
0188 
0189     /** random number from <0.0, range) */
0190     Value random(Number range = 1.0);
0191     Value random(Value range);
0192 
0193     /** some computational functions */
0194     Value fact(const Value &which);
0195     Value fact(const Value &which, const Value &end);
0196     Value fact(int which, int end = 0);
0197     /** Number factorial (every other number multiplied) */
0198     Value factDouble(int which);
0199     Value factDouble(Value which);
0200 
0201     /** combinations */
0202     Value combin(int n, int k);
0203     Value combin(Value n, Value k);
0204 
0205     /** greatest common divisor */
0206     Value gcd(const Value &a, const Value &b);
0207     /** lowest common multiplicator */
0208     Value lcm(const Value &a, const Value &b);
0209 
0210     /** base conversion 10 -> base */
0211     Value base(const Value &val, int base = 16, int prec = 0, int minLength = 0);
0212     /** base conversion base -> 10 */
0213     Value fromBase(const Value &val, int base = 16);
0214 
0215     /** goniometric functions */
0216     Value sin(const Value &number);
0217     Value cos(const Value &number);
0218     Value tg(const Value &number);
0219     Value cotg(const Value &number);
0220     Value asin(const Value &number);
0221     Value acos(const Value &number);
0222     Value atg(const Value &number);
0223     Value atan2(const Value &y, const Value &x);
0224 
0225     /** hyperbolic functions */
0226     Value sinh(const Value &number);
0227     Value cosh(const Value &number);
0228     Value tgh(const Value &number);
0229     Value asinh(const Value &number);
0230     Value acosh(const Value &number);
0231     Value atgh(const Value &number);
0232 
0233     /** some statistical stuff
0234       TODO: we may want to move these over to a separate class or something,
0235       as the functions are mostly big */
0236     Value phi(Value x);
0237     Value gauss(Value xx);
0238     Value gaussinv(Value xx);
0239     Value GetGamma(Value _x);
0240     Value GetLogGamma(Value _x);
0241     Value GetGammaDist(Value _x, Value _alpha,
0242                        Value _beta);
0243     Value GetBeta(Value _x, Value _alpha,
0244                   Value _beta);
0245 
0246     /** bessel functions - may also end up being separated from here */
0247     Value besseli(Value v, Value x);
0248     Value besselj(Value v, Value x);
0249     Value besselk(Value v, Value x);
0250     Value besseln(Value v, Value x);
0251 
0252     /** error functions (see: man erf) */
0253     Value erf(Value x);
0254     Value erfc(Value x);
0255 
0256     /** array/range walking */
0257     void arrayWalk(const Value &range, Value &res,
0258                    arrayWalkFunc func, Value param);
0259     /** Walk the array in function-like style.
0260     This method is here to avoid duplication in function handlers. */
0261     void arrayWalk(QVector<Value> &range, Value &res,
0262                    arrayWalkFunc func, Value param);
0263     Value arrayMap(const Value &array, arrayMapFunc func, const Value &param);
0264     Value twoArrayMap(const Value &array1, arrayMapFunc func, const Value &array2);
0265     void twoArrayWalk(const Value &a1, const Value &a2,
0266                       Value &res, arrayWalkFunc func);
0267     void twoArrayWalk(QVector<Value> &a1,
0268                       QVector<Value> &a2, Value &res, arrayWalkFunc func);
0269     arrayWalkFunc awFunc(const QString &name);
0270     void registerAwFunc(const QString &name, arrayWalkFunc func);
0271 
0272     /** basic range functions */
0273     // if full is true, A-version is used (means string/bool values included)
0274     Value sum(const Value &range, bool full = true);
0275     Value sumsq(const Value &range, bool full = true);
0276     Value sumIf(const Value &range, const Condition &cond);
0277     Value sumIf(const Cell &sumRangeStart,
0278                 const Value &checkRange, const Condition &cond);
0279     Value sumIfs(const Cell &sumRangeStart,
0280                  QList<Value> c_Range, QList<Condition> cond, const float limit);
0281     Value averageIf(const Value &range, const Condition &cond);
0282     Value averageIf(const Cell &avgRangeStart,
0283                 const Value &checkRange, const Condition &cond);
0284     Value averageIfs(const Cell &avgRangeStart,
0285                  QList<Value> c_Range, QList<Condition> cond, const float limit);
0286     int count(const Value &range, bool full = true);
0287     int countIf(const Value &range, const Condition &cond);
0288     Value countIfs(const Cell &cntRangeStart, QList<Value> c_range, QList<Condition> cond, const float limit);
0289     Value avg(const Value &range, bool full = true);
0290     Value max(const Value &range, bool full = true);
0291     Value min(const Value &range, bool full = true);
0292     Value product(const Value &range, Value init,
0293                   bool full = true);
0294     Value stddev(const Value &range, bool full = true);
0295     Value stddev(const Value &range, Value avg,
0296                  bool full = true);
0297     Value stddevP(const Value &range, bool full = true);
0298     Value stddevP(const Value &range, Value avg,
0299                   bool full = true);
0300 
0301     /** range functions using value lists */
0302     Value sum(QVector<Value> range, bool full = true);
0303     int count(QVector<Value> range, bool full = true);
0304     Value avg(QVector<Value> range, bool full = true);
0305     Value max(QVector<Value> range, bool full = true);
0306     Value min(QVector<Value> range, bool full = true);
0307     Value product(QVector<Value> range, Value init,
0308                   bool full = true);
0309     Value stddev(QVector<Value> range, bool full = true);
0310     Value stddev(QVector<Value> range, Value avg,
0311                  bool full = true);
0312     Value stddevP(QVector<Value> range, bool full = true);
0313     Value stddevP(QVector<Value> range, Value avg,
0314                   bool full = true);
0315 
0316     /**
0317       This method parses the condition in string text to the condition cond.
0318       It sets the condition's type and value.
0319     */
0320     void getCond(Condition &cond, Value val);
0321 
0322     /**
0323       Returns true if value d matches the condition cond, built with getCond().
0324       Otherwise, it returns false.
0325     */
0326     bool matches(const Condition &cond, Value d);
0327 
0328     /** return formatting for the result, based on formattings of input values */
0329     Value::Format format(Value a, Value b);
0330 
0331 protected:
0332     ValueConverter* converter;
0333 
0334     /** registered array-walk functions */
0335     std::map<QString, arrayWalkFunc> awFuncs;
0336 };
0337 
0338 inline bool approxEqual(double a, double b)
0339 {
0340     if (a == b)
0341         return true;
0342     double x = a - b;
0343     return (x < 0.0 ? -x : x)
0344            < ((a < 0.0 ? -a : a) *(1.0 / (16777216.0 * 16777216.0)));
0345 }
0346 
0347 inline double approxFloor(double a)
0348 {
0349     double b = floor(a);
0350     // The second approxEqual() is necessary for values that are near the limit
0351     // of numbers representable with 4 bits stripped off. (#i12446#)
0352     if (approxEqual(a - 1.0, b) && !approxEqual(a, b))
0353         return b + 1.0;
0354     return b;
0355 }
0356 
0357 } // namespace Sheets
0358 } // namespace Calligra
0359 
0360 
0361 #endif // CALLIGRA_SHEETS_VALUECALC
0362