00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "valuecalc.h"
00021
00022 #include "valueconverter.h"
00023
00024 #include <kdebug.h>
00025 #include <errno.h>
00026 #include <float.h>
00027 #include <math.h>
00028 #include <stdlib.h>
00029 #include <time.h>
00030
00031 using namespace KSpread;
00032
00033
00034
00035
00036 void awSum (ValueCalc *c, Value &res, Value val, Value)
00037 {
00038 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00039 res = c->add (res, val);
00040 }
00041
00042 void awSumA (ValueCalc *c, Value &res, Value val, Value)
00043 {
00044 if (!val.isEmpty())
00045 res = c->add (res, val);
00046 }
00047
00048 void awSumSq (ValueCalc *c, Value &res, Value val, Value)
00049 {
00050 if (!val.isEmpty())
00051 res = c->add (res, c->sqr (val));
00052 }
00053
00054 void awSumSqA (ValueCalc *c, Value &res, Value val, Value)
00055 {
00056 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00057 res = c->add (res, c->sqr (val));
00058 }
00059
00060 void awCount (ValueCalc *c, Value &res, Value val, Value)
00061 {
00062 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00063 res = c->add (res, 1);
00064 }
00065
00066 void awCountA (ValueCalc *c, Value &res, Value val, Value)
00067 {
00068 if (!val.isEmpty())
00069 res = c->add (res, 1);
00070 }
00071
00072 void awMax (ValueCalc *c, Value &res, Value val, Value)
00073 {
00074 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00075 if (res.isEmpty())
00076 res = val;
00077 else
00078 if (c->greater (val, res)) res = val;
00079 }
00080
00081 void awMaxA (ValueCalc *c, Value &res, Value val, Value)
00082 {
00083 if (!val.isEmpty())
00084 if (res.isEmpty())
00085
00086 res = c->conv()->asNumeric (val);
00087 else
00088 if (c->greater (val, res))
00089
00090 res = c->conv()->asNumeric (val);
00091 }
00092
00093 void awMin (ValueCalc *c, Value &res, Value val, Value)
00094 {
00095 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00096 if (res.isEmpty())
00097 res = val;
00098 else
00099 if (c->lower (val, res)) res = val;
00100 }
00101
00102 void awMinA (ValueCalc *c, Value &res, Value val, Value)
00103 {
00104 if (!val.isEmpty())
00105 if (res.isEmpty())
00106
00107 res = c->conv()->asNumeric (val);
00108 else
00109 if (c->lower (val, res))
00110
00111 res = c->conv()->asNumeric (val);
00112 }
00113
00114 void awProd (ValueCalc *c, Value &res, Value val, Value)
00115 {
00116 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00117 res = c->mul (res, val);
00118 }
00119
00120 void awProdA (ValueCalc *c, Value &res, Value val, Value)
00121 {
00122 if (!val.isEmpty())
00123 res = c->mul (res, val);
00124 }
00125
00126
00127 void awDevSq (ValueCalc *c, Value &res, Value val,
00128 Value avg)
00129 {
00130 if (!val.isEmpty())
00131 res = c->add (res, c->sqr (c->sub (val, avg)));
00132 }
00133
00134
00135 void awDevSqA (ValueCalc *c, Value &res, Value val,
00136 Value avg)
00137 {
00138 if ((!val.isEmpty()) && (!val.isBoolean()) && (!val.isString()))
00139 res = c->add (res, c->sqr (c->sub (val, avg)));
00140 }
00141
00142
00143 bool isDate (Value val) {
00144 Value::Format fmt = val.format();
00145 if ((fmt == Value::fmt_Date) || (fmt == Value::fmt_DateTime))
00146 return true;
00147 return false;
00148 }
00149
00150
00151
00152
00153
00154 ValueCalc::ValueCalc (ValueConverter* c): converter( c )
00155 {
00156
00157 srand (time (0));
00158
00159
00160 registerAwFunc ("sum", awSum);
00161 registerAwFunc ("suma", awSumA);
00162 registerAwFunc ("sumsq", awSumSq);
00163 registerAwFunc ("sumsqa", awSumSqA);
00164 registerAwFunc ("count", awCount);
00165 registerAwFunc ("counta", awCountA);
00166 registerAwFunc ("max", awMax);
00167 registerAwFunc ("maxa", awMaxA);
00168 registerAwFunc ("min", awMin);
00169 registerAwFunc ("mina", awMinA);
00170 registerAwFunc ("prod", awProd);
00171 registerAwFunc ("proda", awProdA);
00172 registerAwFunc ("devsq", awDevSq);
00173 registerAwFunc ("devsqa", awDevSq);
00174 }
00175
00176 Value ValueCalc::add (const Value &a, const Value &b)
00177 {
00178 if (a.isError()) return a;
00179 if (b.isError()) return b;
00180 Value res;
00181 if (a.isInteger() && b.isEmpty() || a.isEmpty() && b.isInteger()
00182 || a.isInteger() && b.isInteger())
00183 {
00184 int aa, bb;
00185 aa = converter->asInteger (a).asInteger();
00186 bb = converter->asInteger (b).asInteger();
00187 res = Value (aa + bb);
00188 }
00189 else
00190 {
00191 double aa, bb;
00192 aa = converter->asFloat (a).asFloat();
00193 bb = converter->asFloat (b).asFloat();
00194 res = Value (aa + bb);
00195 }
00196
00197 if (a.isNumber() || a.isEmpty())
00198 res.setFormat (format (a.format(), b.format()));
00199
00200 if (isDate(a) && isDate(b))
00201 res.setFormat (Value::fmt_Number);
00202
00203 return res;
00204 }
00205
00206 Value ValueCalc::sub (const Value &a, const Value &b)
00207 {
00208 if (a.isError()) return a;
00209 if (b.isError()) return b;
00210 double aa, bb;
00211 aa = converter->asFloat (a).asFloat();
00212 bb = converter->asFloat (b).asFloat();
00213 Value res = Value (aa - bb);
00214
00215 if (a.isNumber() || a.isEmpty())
00216 res.setFormat (format (a.format(), b.format()));
00217
00218 if (isDate(a) && isDate(b))
00219 res.setFormat (Value::fmt_Number);
00220
00221 return res;
00222 }
00223
00224 Value ValueCalc::mul (const Value &a, const Value &b)
00225 {
00226 if (a.isError()) return a;
00227 if (b.isError()) return b;
00228 double aa, bb;
00229 aa = converter->asFloat (a).asFloat();
00230 bb = converter->asFloat (b).asFloat();
00231 Value res = Value (aa * bb);
00232
00233 if (a.isNumber() || a.isEmpty())
00234 res.setFormat (format (a.format(), b.format()));
00235
00236 if (isDate(a) && isDate(b))
00237 res.setFormat (Value::fmt_Number);
00238
00239 return res;
00240 }
00241
00242 Value ValueCalc::div (const Value &a, const Value &b)
00243 {
00244 if (a.isError()) return a;
00245 if (b.isError()) return b;
00246 double aa, bb;
00247 aa = converter->asFloat (a).asFloat();
00248 bb = converter->asFloat (b).asFloat();
00249 Value res;
00250 if (bb == 0.0)
00251 return Value::errorDIV0();
00252 else
00253 res = Value (aa / bb);
00254
00255 if (a.isNumber() || a.isEmpty())
00256 res.setFormat (format (a.format(), b.format()));
00257
00258 if (isDate(a) && isDate(b))
00259 res.setFormat (Value::fmt_Number);
00260
00261 return res;
00262 }
00263
00264 Value ValueCalc::mod (const Value &a, const Value &b)
00265 {
00266 if (a.isError()) return a;
00267 if (b.isError()) return b;
00268 double aa, bb;
00269 aa = converter->asFloat (a).asFloat();
00270 bb = converter->asFloat (b).asFloat();
00271 Value res;
00272 if (bb == 0.0)
00273 return Value::errorDIV0();
00274 else
00275 {
00276 double m = fmod (aa, bb);
00277
00278
00279
00280
00281 if ((bb > 0) && (aa < 0))
00282 while (m < 0) m += bb;
00283 if (bb < 0)
00284 {
00285
00286 while (m < bb) m -= bb;
00287 while (m > 0) m += bb;
00288 }
00289
00290 res = Value (m);
00291 }
00292
00293 if (a.isNumber() || a.isEmpty())
00294 res.setFormat (format (a.format(), b.format()));
00295 if (isDate(a) && isDate(b))
00296 res.setFormat (Value::fmt_Number);
00297
00298 return res;
00299 }
00300
00301 Value ValueCalc::pow (const Value &a, const Value &b)
00302 {
00303 if (a.isError()) return a;
00304 if (b.isError()) return b;
00305 double aa, bb;
00306 aa = converter->asFloat (a).asFloat();
00307 bb = converter->asFloat (b).asFloat();
00308 Value res = Value (::pow (aa, bb));
00309
00310 if (a.isNumber() || a.isEmpty())
00311 res.setFormat (format (a.format(), b.format()));
00312
00313 if (isDate(a) || isDate(b))
00314 res.setFormat (Value::fmt_Number);
00315
00316 return res;
00317 }
00318
00319 Value ValueCalc::sqr (const Value &a)
00320 {
00321 if (a.isError()) return a;
00322 return mul (a, a);
00323 }
00324
00325 Value ValueCalc::sqrt (const Value &a)
00326 {
00327 if (a.isError()) return a;
00328 Value res = Value (::sqrt (converter->asFloat(a).asFloat()));
00329 if (a.isNumber() || a.isEmpty())
00330 res.setFormat (a.format());
00331
00332 if (isDate(a))
00333 res.setFormat (Value::fmt_Number);
00334
00335 return res;
00336 }
00337
00338 Value ValueCalc::add (const Value &a, double b)
00339 {
00340 if (a.isError()) return a;
00341 Value res = Value (converter->asFloat(a).asFloat() + b);
00342
00343 if (a.isNumber() || a.isEmpty())
00344 res.setFormat (a.format());
00345
00346 return res;
00347 }
00348
00349 Value ValueCalc::sub (const Value &a, double b)
00350 {
00351 if (a.isError()) return a;
00352 Value res = Value (converter->asFloat(a).asFloat() - b);
00353
00354 if (a.isNumber() || a.isEmpty())
00355 res.setFormat (a.format());
00356
00357 return res;
00358 }
00359
00360 Value ValueCalc::mul (const Value &a, double b)
00361 {
00362 if (a.isError()) return a;
00363 Value res = Value (converter->asFloat(a).asFloat() * b);
00364
00365 if (a.isNumber() || a.isEmpty())
00366 res.setFormat (a.format());
00367
00368 return res;
00369 }
00370
00371 Value ValueCalc::div (const Value &a, double b)
00372 {
00373 if (a.isError()) return a;
00374 Value res;
00375 if (b == 0.0)
00376 return Value::errorDIV0();
00377
00378 res = Value (converter->asFloat(a).asFloat() / b);
00379
00380 if (a.isNumber() || a.isEmpty())
00381 res.setFormat (a.format());
00382
00383 return res;
00384 }
00385
00386 Value ValueCalc::pow (const Value &a, double b)
00387 {
00388 if (a.isError()) return a;
00389 Value res = Value (::pow (converter->asFloat(a).asFloat(), b));
00390
00391 if (a.isNumber() || a.isEmpty())
00392 res.setFormat (a.format());
00393
00394 return res;
00395 }
00396
00397 Value ValueCalc::abs (const Value &a)
00398 {
00399 if (a.isError()) return a;
00400 return Value (fabs (converter->asFloat (a).asFloat()));
00401 }
00402
00403 bool ValueCalc::isZero (const Value &a)
00404 {
00405 if (a.isError()) return false;
00406 return (converter->asFloat (a).asFloat() == 0.0);
00407 }
00408
00409 bool ValueCalc::isEven (const Value &a)
00410 {
00411 if (a.isError()) return false;
00412 return ((converter->asInteger (a).asInteger() % 2) == 0);
00413 }
00414
00415 bool ValueCalc::equal (const Value &a, const Value &b)
00416 {
00417 return (converter->asFloat (a).asFloat() == converter->asFloat (b).asFloat());
00418 }
00419
00420
00421
00422
00423
00424
00425
00426 bool ValueCalc::approxEqual (const Value &a, const Value &b)
00427 {
00428 double aa = converter->asFloat (a).asFloat();
00429 double bb = converter->asFloat (b).asFloat();
00430 if (aa == bb)
00431 return true;
00432 double x = aa - bb;
00433 return (x < 0.0 ? -x : x) < ((aa < 0.0 ? -aa : aa) * DBL_EPSILON);
00434 }
00435
00436 bool ValueCalc::strEqual (const Value &a, const Value &b)
00437 {
00438 return (converter->asString (a).asString() == converter->asString (b).asString());
00439 }
00440
00441 bool ValueCalc::greater (const Value &a, const Value &b)
00442 {
00443 double aa = converter->asFloat (a).asFloat();
00444 double bb = converter->asFloat (b).asFloat();
00445 return (aa > bb);
00446 }
00447
00448 bool ValueCalc::gequal (const Value &a, const Value &b)
00449 {
00450 return (greater (a,b) || approxEqual (a,b));
00451 }
00452
00453 bool ValueCalc::lower (const Value &a, const Value &b)
00454 {
00455 return greater (b, a);
00456 }
00457
00458 Value ValueCalc::roundDown (const Value &a,
00459 const Value &digits) {
00460 return roundDown (a, converter->asInteger (digits).asInteger());
00461 }
00462
00463 Value ValueCalc::roundUp (const Value &a,
00464 const Value &digits) {
00465 return roundUp (a, converter->asInteger (digits).asInteger());
00466 }
00467
00468 Value ValueCalc::round (const Value &a,
00469 const Value &digits) {
00470 return round (a, converter->asInteger (digits).asInteger());
00471 }
00472
00473 Value ValueCalc::roundDown (const Value &a, int digits)
00474 {
00475
00476 Value val = a;
00477 if (digits > 0)
00478 for (int i = 0; i < digits; ++i)
00479 val = mul (val, 10);
00480 if (digits < 0)
00481 for (int i = 0; i < digits; ++i)
00482 val = div (val, 10);
00483
00484 val = Value (floor (converter->asFloat (val).asFloat()));
00485
00486 if (digits > 0)
00487 for (int i = 0; i < digits; ++i)
00488 val = div (val, 10);
00489 if (digits < 0)
00490 for (int i = 0; i < digits; ++i)
00491 val = mul (val, 10);
00492 return val;
00493 }
00494
00495 Value ValueCalc::roundUp (const Value &a, int digits)
00496 {
00497
00498 Value val = a;
00499 if (digits > 0)
00500 for (int i = 0; i < digits; ++i)
00501 val = mul (val, 10);
00502 if (digits < 0)
00503 for (int i = 0; i < digits; ++i)
00504 val = div (val, 10);
00505
00506 val = Value (ceil (converter->asFloat (val).asFloat()));
00507
00508 if (digits > 0)
00509 for (int i = 0; i < digits; ++i)
00510 val = div (val, 10);
00511 if (digits < 0)
00512 for (int i = 0; i < digits; ++i)
00513 val = mul (val, 10);
00514 return val;
00515 }
00516
00517 Value ValueCalc::round (const Value &a, int digits)
00518 {
00519
00520 Value val = a;
00521 if (digits > 0)
00522 for (int i = 0; i < digits; ++i)
00523 val = mul (val, 10);
00524 if (digits < 0)
00525 for (int i = 0; i < digits; ++i)
00526 val = div (val, 10);
00527
00528 val = Value (int(converter->asFloat (val).asFloat()+0.5));
00529
00530 if (digits > 0)
00531 for (int i = 0; i < digits; ++i)
00532 val = div (val, 10);
00533 if (digits < 0)
00534 for (int i = 0; i < digits; ++i)
00535 val = mul (val, 10);
00536 return val;
00537 }
00538
00539 int ValueCalc::sign (const Value &a)
00540 {
00541 double val = converter->asFloat (a).asFloat ();
00542 if (val == 0) return 0;
00543 if (val > 0) return 1;
00544 return -1;
00545 }
00546
00547
00548 Value ValueCalc::log (const Value &number,
00549 const Value &base)
00550 {
00551 double logbase = converter->asFloat (base).asFloat();
00552 if (logbase == 1.0)
00553 return Value::errorDIV0();
00554 if (logbase <= 0.0)
00555 return Value::errorNA();
00556
00557 logbase = log10 (logbase);
00558 Value res = Value (log10 (converter->asFloat (number).asFloat()) / logbase);
00559
00560 if (number.isNumber() || number.isEmpty())
00561 res.setFormat (number.format());
00562
00563 return res;
00564 }
00565
00566 Value ValueCalc::ln (const Value &number)
00567 {
00568 Value res = Value (::log (converter->asFloat (number).asFloat()));
00569
00570 if (number.isNumber() || number.isEmpty())
00571 res.setFormat (number.format());
00572
00573 return res;
00574 }
00575
00576 Value ValueCalc::log (const Value &number, double base)
00577 {
00578 if (base <= 0.0)
00579 return Value::errorNA();
00580 if (base == 1.0)
00581 return Value::errorDIV0();
00582
00583 double num = converter->asFloat (number).asFloat();
00584 Value res = Value (log10 (num) / log10 (base));
00585
00586 if (number.isNumber() || number.isEmpty())
00587 res.setFormat (number.format());
00588
00589 return res;
00590 }
00591
00592 Value ValueCalc::exp (const Value &number)
00593 {
00594 return Value (::exp (converter->asFloat (number).asFloat()));
00595 }
00596
00597 Value ValueCalc::pi ()
00598 {
00599
00600
00601
00602 return Value (M_PI);
00603 }
00604
00605 Value ValueCalc::eps ()
00606 {
00607
00608
00609 return Value (DBL_EPSILON);
00610 }
00611
00612 Value ValueCalc::random (double range)
00613 {
00614 return Value (range * (double) rand() / (RAND_MAX + 1.0));
00615 }
00616
00617 Value ValueCalc::random (Value range)
00618 {
00619 return random (converter->asFloat (range).asFloat());
00620 }
00621
00622 Value ValueCalc::fact (const Value &which)
00623 {
00624
00625
00626 return fact (converter->asInteger (which).asInteger());
00627 }
00628
00629 Value ValueCalc::fact (const Value &which,
00630 const Value &end)
00631 {
00632
00633
00634 return fact (converter->asInteger (which).asInteger(),
00635 converter->asInteger (end).asInteger ());
00636 }
00637
00638 Value ValueCalc::fact (int which, int end) {
00639 if (which < 0)
00640 return Value (-1);
00641 if (which == 0)
00642 return Value (1);
00643
00644 if (which == end)
00645 return Value (1);
00646
00647 return (mul (fact (which-1, end), which));
00648 }
00649
00650 Value ValueCalc::factDouble (int which)
00651 {
00652 if (which < 0)
00653 return Value (-1);
00654 if ((which == 0) || (which == 1))
00655 return Value (1);
00656
00657 return (mul (factDouble (which-2), which));
00658 }
00659
00660 Value ValueCalc::factDouble (Value which)
00661 {
00662 return factDouble (converter->asInteger (which).asInteger());
00663 }
00664
00665 Value ValueCalc::combin (int n, int k)
00666 {
00667 if (n >= 15)
00668 {
00669 double result = ::exp(lgamma (n + 1) - lgamma (k + 1) - lgamma (n-k+1));
00670 return Value (floor(result + 0.5));
00671 }
00672 else
00673 return div (div (fact (n), fact (k)), fact (n - k));
00674 }
00675
00676 Value ValueCalc::combin (Value n, Value k)
00677 {
00678 int nn = converter->asInteger (n).asInteger();
00679 int kk = converter->asInteger (k).asInteger();
00680 return combin (nn, kk);
00681 }
00682
00683 Value ValueCalc::gcd (const Value &a, const Value &b)
00684 {
00685
00686 Value aa = round (a);
00687 Value bb = round (b);
00688
00689 if (approxEqual (aa, bb)) return aa;
00690
00691 if (aa.isZero()) return bb;
00692 if (bb.isZero()) return aa;
00693
00694
00695 if (greater (aa, bb))
00696 return gcd (bb, mod (aa, bb));
00697 else
00698 return gcd (aa, mod (bb, aa));
00699 }
00700
00701 Value ValueCalc::lcm (const Value &a, const Value &b)
00702 {
00703 Value aa = round (a);
00704 Value bb = round (b);
00705
00706 if (approxEqual (aa, bb)) return aa;
00707
00708 if (aa.isZero()) return bb;
00709 if (bb.isZero()) return aa;
00710
00711 Value g = gcd (aa, bb);
00712 if (g.isZero())
00713 return mul (aa, bb);
00714
00715 return div (mul (aa, bb), g);
00716 }
00717
00718 Value ValueCalc::base (const Value &val, int base, int prec)
00719 {
00720 if (base == 10) return round (val, prec);
00721 if (prec < 0) prec = 2;
00722 if ((base < 2) || (base > 36))
00723 return Value::errorVALUE();
00724
00725 double value = converter->asFloat (val).asFloat();
00726 QString result = QString::number ((int)value, base);
00727
00728 if (prec > 0)
00729 {
00730 result += "."; value = value - (int)value;
00731
00732 int ix;
00733 for( int i = 0; i < prec; i++ )
00734 {
00735 ix = (int) value * base;
00736 result += "0123456789abcdefghijklmnopqrstuvwxyz"[ix];
00737 value = base * (value - (double)ix/base);
00738 }
00739 }
00740
00741 return Value (result.upper());
00742 }
00743
00744 Value ValueCalc::fromBase (const Value &val, int base)
00745 {
00746 QString str = converter->asString (val).asString();
00747 bool ok;
00748 double num = str.toLong (&ok, base);
00749 if (ok)
00750 return Value (num);
00751 return Value::errorVALUE();
00752 }
00753
00754
00755 Value ValueCalc::sin (const Value &number)
00756 {
00757 Value res = Value (::sin (converter->asFloat (number).asFloat()));
00758
00759 if (number.isNumber() || number.isEmpty())
00760 res.setFormat (number.format());
00761
00762 return res;
00763 }
00764
00765 Value ValueCalc::cos (const Value &number)
00766 {
00767 Value res = Value (::cos (converter->asFloat (number).asFloat()));
00768
00769 if (number.isNumber() || number.isEmpty())
00770 res.setFormat (number.format());
00771
00772 return res;
00773 }
00774
00775 Value ValueCalc::tg (const Value &number)
00776 {
00777 Value res = Value (::tan (converter->asFloat (number).asFloat()));
00778
00779 if (number.isNumber() || number.isEmpty())
00780 res.setFormat (number.format());
00781
00782 return res;
00783 }
00784
00785 Value ValueCalc::cotg (const Value &number)
00786 {
00787 Value res = Value (div (1, ::tan (converter->asFloat (number).asFloat())));
00788
00789 if (number.isNumber() || number.isEmpty())
00790 res.setFormat (number.format());
00791
00792 return res;
00793 }
00794
00795 Value ValueCalc::asin (const Value &number)
00796 {
00797 errno = 0;
00798 Value res = Value (::asin (converter->asFloat (number).asFloat()));
00799 if (errno)
00800 return Value::errorVALUE();
00801
00802 if (number.isNumber() || number.isEmpty())
00803 res.setFormat (number.format());
00804
00805 return res;
00806 }
00807
00808 Value ValueCalc::acos (const Value &number)
00809 {
00810 errno = 0;
00811 Value res = Value (::acos (converter->asFloat (number).asFloat()));
00812 if (errno)
00813 return Value::errorVALUE();
00814
00815 if (number.isNumber() || number.isEmpty())
00816 res.setFormat (number.format());
00817
00818 return res;
00819 }
00820
00821 Value ValueCalc::atg (const Value &number)
00822 {
00823 errno = 0;
00824 Value res = Value (::atan (converter->asFloat (number).asFloat()));
00825 if (errno)
00826 return Value::errorVALUE();
00827
00828 if (number.isNumber() || number.isEmpty())
00829 res.setFormat (number.format());
00830
00831 return res;
00832 }
00833
00834 Value ValueCalc::atan2 (const Value &y, const Value &x)
00835 {
00836 double yy = converter->asFloat (y).asFloat();
00837 double xx = converter->asFloat (x).asFloat();
00838 return Value (::atan2 (yy, xx));
00839 }
00840
00841 Value ValueCalc::sinh (const Value &number)
00842 {
00843 Value res = Value (::sinh (converter->asFloat (number).asFloat()));
00844
00845 if (number.isNumber() || number.isEmpty())
00846 res.setFormat (number.format());
00847
00848 return res;
00849 }
00850
00851 Value ValueCalc::cosh (const Value &number)
00852 {
00853 Value res = Value (::cosh (converter->asFloat (number).asFloat()));
00854
00855 if (number.isNumber() || number.isEmpty())
00856 res.setFormat (number.format());
00857
00858 return res;
00859 }
00860
00861 Value ValueCalc::tgh (const Value &number)
00862 {
00863 Value res = Value (::tanh (converter->asFloat (number).asFloat()));
00864
00865 if (number.isNumber() || number.isEmpty())
00866 res.setFormat (number.format());
00867
00868 return res;
00869 }
00870
00871 Value ValueCalc::asinh (const Value &number)
00872 {
00873 errno = 0;
00874 Value res = Value (::asinh (converter->asFloat (number).asFloat()));
00875 if (errno)
00876 return Value::errorVALUE();
00877
00878 if (number.isNumber() || number.isEmpty())
00879 res.setFormat (number.format());
00880
00881 return res;
00882 }
00883
00884 Value ValueCalc::acosh (const Value &number)
00885 {
00886 errno = 0;
00887 Value res = Value (::acosh (converter->asFloat (number).asFloat()));
00888 if (errno)
00889 return Value::errorVALUE();
00890
00891 if (number.isNumber() || number.isEmpty())
00892 res.setFormat (number.format());
00893
00894 return res;
00895 }
00896
00897 Value ValueCalc::atgh (const Value &number)
00898 {
00899 errno = 0;
00900 Value res = Value (::atanh (converter->asFloat (number).asFloat()));
00901 if (errno)
00902 return Value::errorVALUE();
00903
00904 if (number.isNumber() || number.isEmpty())
00905 res.setFormat (number.format());
00906
00907 return res;
00908 }
00909
00910 Value ValueCalc::phi (Value x)
00911 {
00912 Value constant (0.39894228040143268);
00913
00914
00915 Value x2neg = mul (sqr (x), -1);
00916 return mul (constant, exp (div (x2neg, 2.0)));
00917 }
00918
00919 static double taylor_helper (double* pPolynom, uint nMax, double x)
00920 {
00921 double nVal = pPolynom[nMax];
00922 for (int i = nMax-1; i >= 0; i--) {
00923 nVal = pPolynom[i] + (nVal * x);
00924 }
00925 return nVal;
00926 }
00927
00928 Value ValueCalc::gauss (Value xx)
00929
00930 {
00931 double x = converter->asFloat (xx).asFloat();
00932
00933 double t0[] =
00934 { 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
00935 -0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
00936 0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
00937 0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
00938 double t2[] =
00939 { 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
00940 0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
00941 0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
00942 0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
00943 0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
00944 -0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
00945 -0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
00946 -0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
00947 double t4[] =
00948 { 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
00949 0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
00950 -0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
00951 -0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
00952 0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
00953 0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
00954 0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
00955 double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
00956
00957 double xAbs = fabs(x);
00958 uint xShort = static_cast<uint>(floor(xAbs));
00959 double nVal = 0.0;
00960 if (xShort == 0)
00961 nVal = taylor_helper(t0, 11, (xAbs * xAbs)) * xAbs;
00962 else if ((xShort >= 1) && (xShort <= 2))
00963 nVal = taylor_helper(t2, 23, (xAbs - 2.0));
00964 else if ((xShort >= 3) && (xShort <= 4))
00965 nVal = taylor_helper(t4, 20, (xAbs - 4.0));
00966 else
00967 {
00968 double phiAbs = converter->asFloat (phi (xAbs)).asFloat();
00969 nVal = 0.5 + phiAbs * taylor_helper(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs;
00970 }
00971
00972 if (x < 0.0)
00973 return Value (-nVal);
00974 else
00975 return Value (nVal);
00976 }
00977
00978 Value ValueCalc::gaussinv (Value xx)
00979
00980 {
00981 double x = converter->asFloat (xx).asFloat();
00982
00983 double q,t,z;
00984
00985 q=x-0.5;
00986
00987 if(fabs(q)<=.425)
00988 {
00989 t=0.180625-q*q;
00990
00991 z=
00992 q*
00993 (
00994 (
00995 (
00996 (
00997 (
00998 (
00999 (
01000 t*2509.0809287301226727+33430.575583588128105
01001 )
01002 *t+67265.770927008700853
01003 )
01004 *t+45921.953931549871457
01005 )
01006 *t+13731.693765509461125
01007 )
01008 *t+1971.5909503065514427
01009 )
01010 *t+133.14166789178437745
01011 )
01012 *t+3.387132872796366608
01013 )
01014 /
01015 (
01016 (
01017 (
01018 (
01019 (
01020 (
01021 (
01022 t*5226.495278852854561+28729.085735721942674
01023 )
01024 *t+39307.89580009271061
01025 )
01026 *t+21213.794301586595867
01027 )
01028 *t+5394.1960214247511077
01029 )
01030 *t+687.1870074920579083
01031 )
01032 *t+42.313330701600911252
01033 )
01034 *t+1.0
01035 );
01036
01037 }
01038 else
01039 {
01040 if(q>0) t=1-x;
01041 else t=x;
01042
01043 t=::sqrt(-::log(t));
01044
01045 if(t<=5.0)
01046 {
01047 t+=-1.6;
01048
01049 z=
01050 (
01051 (
01052 (
01053 (
01054 (
01055 (
01056 (
01057 t*7.7454501427834140764e-4+0.0227238449892691845833
01058 )
01059 *t+0.24178072517745061177
01060 )
01061 *t+1.27045825245236838258
01062 )
01063 *t+3.64784832476320460504
01064 )
01065 *t+5.7694972214606914055
01066 )
01067 *t+4.6303378461565452959
01068 )
01069 *t+1.42343711074968357734
01070 )
01071 /
01072 (
01073 (
01074 (
01075 (
01076 (
01077 (
01078 (
01079 t*1.05075007164441684324e-9+5.475938084995344946e-4
01080 )
01081 *t+0.0151986665636164571966
01082 )
01083 *t+0.14810397642748007459
01084 )
01085 *t+0.68976733498510000455
01086 )
01087 *t+1.6763848301838038494
01088 )
01089 *t+2.05319162663775882187
01090 )
01091 *t+1.0
01092 );
01093
01094 }
01095 else
01096 {
01097 t+=-5.0;
01098
01099 z=
01100 (
01101 (
01102 (
01103 (
01104 (
01105 (
01106 (
01107 t*2.01033439929228813265e-7+2.71155556874348757815e-5
01108 )
01109 *t+0.0012426609473880784386
01110 )
01111 *t+0.026532189526576123093
01112 )
01113 *t+0.29656057182850489123
01114 )
01115 *t+1.7848265399172913358
01116 )
01117 *t+5.4637849111641143699
01118 )
01119 *t+6.6579046435011037772
01120 )
01121 /
01122 (
01123 (
01124 (
01125 (
01126 (
01127 (
01128 (
01129 t*2.04426310338993978564e-15+1.4215117583164458887e-7
01130 )
01131 *t+1.8463183175100546818e-5
01132 )
01133 *t+7.868691311456132591e-4
01134 )
01135 *t+0.0148753612908506148525
01136 )
01137 *t+0.13692988092273580531
01138 )
01139 *t+0.59983220655588793769
01140 )
01141 *t+1.0
01142 );
01143
01144 }
01145
01146 if(q<0.0) z=-z;
01147 }
01148
01149 return Value (z);
01150 }
01151
01152
01153 static double GammaHelp(double& x, bool& bReflect)
01154 {
01155 double c[6] = {76.18009173, -86.50532033, 24.01409822,
01156 -1.231739516, 0.120858003E-2, -0.536382E-5};
01157 if (x >= 1.0)
01158 {
01159 bReflect = false;
01160 x -= 1.0;
01161 }
01162 else
01163 {
01164 bReflect = true;
01165 x = 1.0 - x;
01166 }
01167 double s, anum;
01168 s = 1.0;
01169 anum = x;
01170 for (uint i = 0; i < 6; i++)
01171 {
01172 anum += 1.0;
01173 s += c[i]/anum;
01174 }
01175 s *= 2.506628275;
01176 return s;
01177 }
01178
01179 Value ValueCalc::GetGamma (Value _x)
01180 {
01181 double x = converter->asFloat (_x).asFloat();
01182
01183 bool bReflect;
01184 double G = GammaHelp(x, bReflect);
01185 G = ::pow(x+5.5,x+0.5)*G/::exp(x+5.5);
01186 if (bReflect)
01187 G = M_PI*x/(G*::sin(M_PI*x));
01188 return Value (G);
01189 }
01190
01191 Value ValueCalc::GetLogGamma (Value _x)
01192 {
01193 double x = converter->asFloat (_x).asFloat();
01194
01195 bool bReflect;
01196 double G = GammaHelp(x, bReflect);
01197 G = (x+0.5)*::log(x+5.5)+::log(G)-(x+5.5);
01198 if (bReflect)
01199 G = ::log(M_PI*x)-G-::log(::sin(M_PI*x));
01200 return Value (G);
01201 }
01202
01203 Value ValueCalc::GetGammaDist (Value _x, Value _alpha,
01204 Value _beta)
01205 {
01206 double x = converter->asFloat (_x).asFloat();
01207 double alpha = converter->asFloat (_alpha).asFloat();
01208 double beta = converter->asFloat (_beta).asFloat();
01209
01210 if (x == 0.0)
01211 return Value (0.0);
01212
01213 x /= beta;
01214 double gamma = alpha;
01215
01216 double c = 0.918938533204672741;
01217 double d[10] = {
01218 0.833333333333333333E-1,
01219 -0.277777777777777778E-2,
01220 0.793650793650793651E-3,
01221 -0.595238095238095238E-3,
01222 0.841750841750841751E-3,
01223 -0.191752691752691753E-2,
01224 0.641025641025641025E-2,
01225 -0.295506535947712418E-1,
01226 0.179644372368830573,
01227 -0.139243221690590111E1
01228 };
01229
01230 double dx = x;
01231 double dgamma = gamma;
01232 int maxit = 10000;
01233
01234 double z = dgamma;
01235 double den = 1.0;
01236 while ( z < 10.0 ) {
01237 den *= z;
01238 z += 1.0;
01239 }
01240
01241 double z2 = z*z;
01242 double z3 = z*z2;
01243 double z4 = z2*z2;
01244 double z5 = z2*z3;
01245 double a = ( z - 0.5 ) * ::log(z) - z + c;
01246 double b = d[0]/z + d[1]/z3 + d[2]/z5 + d[3]/(z2*z5) + d[4]/(z4*z5) +
01247 d[5]/(z*z5*z5) + d[6]/(z3*z5*z5) + d[7]/(z5*z5*z5) + d[8]/(z2*z5*z5*z5);
01248
01249
01250 double sum = 1.0 / dgamma;
01251 double term = 1.0 / dgamma;
01252 double cut1 = dx - dgamma;
01253 double cut2 = dx * 10000000000.0;
01254
01255 for ( int i=1; i<=maxit; i++ ) {
01256 double ai = i;
01257 term = dx * term / ( dgamma + ai );
01258 sum += term;
01259 double cutoff = cut1 + ( cut2 * term / sum );
01260 if ( ai > cutoff ) {
01261 double t = sum;
01262
01263 return Value (::exp( dgamma * ::log(dx) - dx - a - b ) * t * den);
01264 }
01265 }
01266
01267 return Value (1.0);
01268 }
01269
01270 Value ValueCalc::GetBeta (Value _x, Value _alpha,
01271 Value _beta)
01272 {
01273 if (equal (_beta, 1.0))
01274 return pow (_x, _alpha);
01275 else if (equal (_alpha, 1.0))
01276
01277 return sub (1.0, pow (sub (1.0, _x), _beta));
01278
01279 double x = converter->asFloat (_x).asFloat();
01280 double alpha = converter->asFloat (_alpha).asFloat();
01281 double beta = converter->asFloat (_beta).asFloat();
01282
01283 double fEps = 1.0E-8;
01284 bool bReflect;
01285 double cf, fA, fB;
01286
01287 if (x < (alpha+1.0)/(alpha+beta+1.0)) {
01288 bReflect = false;
01289 fA = alpha;
01290 fB = beta;
01291 }
01292 else {
01293 bReflect = true;
01294 fA = beta;
01295 fB = alpha;
01296 x = 1.0 - x;
01297 }
01298 if (x < fEps)
01299 cf = 0.0;
01300 else {
01301 double a1, b1, a2, b2, fnorm, rm, apl2m, d2m, d2m1, cfnew;
01302 a1 = 1.0; b1 = 1.0;
01303 b2 = 1.0 - (fA+fB)*x/(fA+1.0);
01304 if (b2 == 0.0) {
01305 a2 = b2;
01306 fnorm = 1.0;
01307 cf = 1.0;
01308 }
01309 else {
01310 a2 = 1.0;
01311 fnorm = 1.0/b2;
01312 cf = a2*fnorm;
01313 }
01314 cfnew = 1.0;
01315 for (uint j = 1; j <= 100; j++) {
01316 rm = (double) j;
01317 apl2m = fA + 2.0*rm;
01318 d2m = rm*(fB-rm)*x/((apl2m-1.0)*apl2m);
01319 d2m1 = -(fA+rm)*(fA+fB+rm)*x/(apl2m*(apl2m+1.0));
01320 a1 = (a2+d2m*a1)*fnorm;
01321 b1 = (b2+d2m*b1)*fnorm;
01322 a2 = a1 + d2m1*a2*fnorm;
01323 b2 = b1 + d2m1*b2*fnorm;
01324 if (b2 != 0.0) {
01325 fnorm = 1.0/b2;
01326 cfnew = a2*fnorm;
01327 if (fabs(cf-cfnew)/cf < fEps)
01328 j = 101;
01329 else
01330 cf = cfnew;
01331 }
01332 }
01333 if (fB < fEps)
01334 b1 = 1.0E30;
01335 else
01336 b1 = ::exp(GetLogGamma(fA).asFloat()+GetLogGamma(fB).asFloat()-
01337 GetLogGamma(fA+fB).asFloat());
01338
01339 cf *= ::pow(x, fA)*::pow(1.0-x,fB)/(fA*b1);
01340 }
01341 if (bReflect)
01342 return Value (1.0-cf);
01343 else
01344 return Value (cf);
01345 }
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 static double ccmath_gaml(double x)
01363 { double g,h;
01364 for(g=1.; x<30. ;g*=x,x+=1.); h=x*x;
01365 g=(x-.5)*log(x)-x+.918938533204672-log(g);
01366 g+=(1.-(1./6.-(1./3.-1./(4.*h))/(7.*h))/(5.*h))/(12.*x);
01367 return g;
01368 }
01369
01370 static double ccmath_psi(int m)
01371 { double s= -.577215664901533; int k;
01372 for(k=1; k<m ;++k) s+=1./k;
01373 return s;
01374 }
01375
01376 static double ccmath_ibes(double v,double x)
01377 { double y,s,t,tp; int p,m;
01378 y=x-9.; if(y>0.) y*=y; tp=v*v*.2+25.;
01379 if(y<tp){ x/=2.; m=(int)x;
01380 if(x>0.) s=t=exp(v*log(x)-ccmath_gaml(v+1.));
01381 else{ if(v>0.) return 0.; else if(v==0.) return 1.;}
01382 for(p=1,x*=x;;++p){ t*=x/(p*(v+=1.)); s+=t;
01383 if(p>m && t<1.e-13*s) break;
01384 }
01385 }
01386 else{ double u,a0=1.57079632679490;
01387 s=t=1./sqrt(x*a0); x*=2.; u=0.;
01388 for(p=1,y=.5; (tp=fabs(t))>1.e-14 ;++p,y+=1.){
01389 t*=(v+y)*(v-y)/(p*x); if(y>v && fabs(t)>=tp) break;
01390 if(!(p&1)) s+=t; else u-=t;
01391 }
01392 x/=2.; s=cosh(x)*s+sinh(x)*u;
01393 }
01394 return s;
01395 }
01396
01397 static double ccmath_kbes(double v,double x)
01398 { double y,s,t,tp,f,a0=1.57079632679490;
01399 int p,k,m;
01400 if(x==0.) return HUGE_VAL;
01401 y=x-10.5; if(y>0.) y*=y; tp=25.+.185*v*v;
01402 if(y<tp && modf(v+.5,&t)!=0.){ y=1.5+.5*v;
01403 if(x<y){ x/=2.; m=(int)x; tp=t=exp(v*log(x)-ccmath_gaml(v+1.));
01404 if(modf(v,&y)==0.){ k=(int)y; tp*=v;
01405 f=2.*log(x)-ccmath_psi(1)-ccmath_psi(k+1);
01406 t/=2.; if(!(k&1)) t= -t; s=f*t;
01407 for(p=1,x*=x;;++p){ f-=1./p+1./(v+=1.);
01408 t*=x/(p*v); s+=(y=t*f);
01409 if(p>m && fabs(y)<1.e-14) break; }
01410 if(k>0){ x= -x; s+=(t=1./(tp*2.));
01411 for(p=1,--k; k>0 ;++p,--k) s+=(t*=x/(p*k)); }
01412 }
01413 else{ f=1./(t*v*2.); t*=a0/sin(2.*a0*v); s=f-t;
01414 for(p=1,x*=x,tp=v;;++p){
01415 t*=x/(p*(v+=1.)); f*= -x/(p*(tp-=1.));
01416 s+=(y=f-t); if(p>m && fabs(y)<1.e-14) break; }
01417 }
01418 }
01419 else{ double tq,h,w,z,r;
01420 t=12./pow(x,.333); k=(int)(t*t); y=2.*(x+k);
01421 m=(int)v; v-=m; tp=v*v-.25; v+=1.; tq=v*v-.25;
01422 for(s=h=1.,r=f=z=w=0.; k>0 ;--k,y-=2.){
01423 t=(y*h-(k+1)*z)/(k-1-tp/k); z=h; f+=(h=t);
01424 t=(y*s-(k+1)*w)/(k-1-tq/k); w=s; r+=(s=t); }
01425 t=sqrt(a0/x)*exp(-x); s*=t/r; h*=t/f; x/=2.; if(m==0) s=h;
01426 for(k=1; k<m ;++k){ t=v*s/x+h; h=s; s=t; v+=1.;}
01427 }
01428 }
01429 else{ s=t=sqrt(a0/x); x*=2.;
01430 for(p=1,y=.5; (tp=fabs(t))>1.e-14 ;++p,y+=1.){
01431 t*=(v+y)*(v-y)/(p*x); if(y>v && fabs(t)>=tp) break; s+=t; }
01432 s*=exp(-x/2.);
01433 }
01434 return s;
01435 }
01436
01437 static double ccmath_jbes(double v,double x)
01438 { double y,s,t,tp; int p,m;
01439 y=x-8.5; if(y>0.) y*=y; tp=v*v/4.+13.69;
01440 if(y<tp){ x/=2.; m=(int)x;
01441 if(x>0.) s=t=exp(v*log(x)-ccmath_gaml(v+1.));
01442 else{ if(v>0.) return 0.; else if(v==0.) return 1.;}
01443 for(p=1,x*= -x;;++p){ t*=x/(p*(v+=1.)); s+=t;
01444 if(p>m && fabs(t)<1.e-13) break;
01445 }
01446 }
01447 else{ double u,a0=1.57079632679490;
01448 s=t=1./sqrt(x*a0); x*=2.; u=0.;
01449 for(p=1,y=.5; (tp=fabs(t))>1.e-14 ;++p,y+=1.){
01450 t*=(v+y)*(v-y)/(p*x); if(y>v && fabs(t)>=tp) break;
01451 if(!(p&1)){ t= -t; s+=t;} else u-=t;
01452 }
01453 y=x/2.-(v+.5)*a0; s=cos(y)*s+sin(y)*u;
01454 }
01455 return s;
01456 }
01457
01458 static double ccmath_nbes(double v,double x)
01459 { double y,s,t,tp,u,f,a0=3.14159265358979;
01460 int p,k,m;
01461 y=x-8.5; if(y>0.) y*=y; tp=v*v/4.+13.69;
01462 if(y<tp){ if(x==0.) return HUGE_VAL;
01463 x/=2.; m=(int)x; u=t=exp(v*log(x)-ccmath_gaml(v+1.));
01464 if(modf(v,&y)==0.){ k=(int)y; u*=v;
01465 f=2.*log(x)-ccmath_psi(1)-ccmath_psi(k+1);
01466 t/=a0; x*= -x; s=f*t;
01467 for(p=1;;++p){ f-=1./p+1./(v+=1.);
01468 t*=x/(p*v); s+=(y=t*f); if(p>m && fabs(y)<1.e-13) break; }
01469 if(k>0){ x= -x; s-=(t=1./(u*a0));
01470 for(p=1,--k; k>0 ;++p,--k) s-=(t*=x/(p*k)); }
01471 }
01472 else{ f=1./(t*v*a0); t/=tan(a0*v); s=t-f;
01473 for(p=1,x*=x,u=v;;++p){
01474 t*= -x/(p*(v+=1.)); f*=x/(p*(u-=1.));
01475 s+=(y=t-f); if(p>m && fabs(y)<1.e-13) break; }
01476 }
01477 }
01478 else{ x*=2.; s=t=2./sqrt(x*a0); u=0.;
01479 for(p=1,y=.5; (tp=fabs(t))>1.e-14 ;++p,y+=1.){
01480 t*=(v+y)*(v-y)/(p*x); if(y>v && fabs(t)>tp) break;
01481 if(!(p&1)){ t= -t; s+=t;} else u+=t;
01482 }
01483 y=(x-(v+.5)*a0)/2.; s=sin(y)*s+cos(y)*u;
01484 }
01485 return s;
01486 }
01487
01488
01489
01490
01491
01492 Value ValueCalc::besseli (Value v, Value x)
01493 {
01494 double vv = converter->asFloat (v).asFloat ();
01495 double xx = converter->asFloat (x).asFloat ();
01496 return Value (ccmath_ibes (vv, xx));
01497 }
01498
01499 Value ValueCalc::besselj (Value v, Value x)
01500 {
01501 double vv = converter->asFloat (v).asFloat ();
01502 double xx = converter->asFloat (x).asFloat ();
01503 return Value (ccmath_jbes (vv, xx));
01504 }
01505
01506 Value ValueCalc::besselk (Value v, Value x)
01507 {
01508 double vv = converter->asFloat (v).asFloat ();
01509 double xx = converter->asFloat (x).asFloat ();
01510 return Value (ccmath_kbes (vv, xx));
01511 }
01512
01513 Value ValueCalc::besseln (Value v, Value x)
01514 {
01515 double vv = converter->asFloat (v).asFloat ();
01516 double xx = converter->asFloat (x).asFloat ();
01517 return Value (ccmath_nbes (vv, xx));
01518 }
01519
01520
01521
01522 Value ValueCalc::erf (Value x)
01523 {
01524 return Value (::erf (converter->asFloat (x).asFloat()));
01525 }
01526
01527 Value ValueCalc::erfc (Value x)
01528 {
01529 return Value (::erfc (converter->asFloat (x).asFloat()));
01530 }
01531
01532
01533
01534 void ValueCalc::arrayWalk (const Value &range,
01535 Value &res, arrayWalkFunc func, Value param)
01536 {
01537 if (res.isError()) return;
01538 if (!range.isArray ())
01539 {
01540 func (this, res, range, param);
01541 return;
01542 }
01543
01544 int rows = range.rows ();
01545 int cols = range.columns ();
01546 for (int r = 0; r < rows; r++)
01547 for (int c = 0; c < cols; c++)
01548 {
01549 Value v = range.element (c, r);
01550 if (v.isArray())
01551 arrayWalk (v, res, func, param);
01552 else {
01553 func (this, res, v, param);
01554 if (res.format() == Value::fmt_None)
01555 res.setFormat (v.format());
01556 }
01557 }
01558 }
01559
01560 void ValueCalc::arrayWalk (QValueVector<Value> &range,
01561 Value &res, arrayWalkFunc func, Value param)
01562 {
01563 if (res.isError()) return;
01564 for (unsigned int i = 0; i < range.count(); ++i)
01565 arrayWalk (range[i], res, func, param);
01566 }
01567
01568 void ValueCalc::twoArrayWalk (const Value &a1, const Value &a2,
01569 Value &res, arrayWalkFunc func)
01570 {
01571 if (res.isError()) return;
01572 if (!a1.isArray ())
01573 {
01574 func (this, res, a1, a2);
01575 return;
01576 }
01577
01578 int rows = a1.rows ();
01579 int cols = a1.columns ();
01580 int rows2 = a2.rows ();
01581 int cols2 = a2.columns ();
01582 if ((rows != rows2) || (cols != cols2)) {
01583 res = Value::errorVALUE();
01584 return;
01585 }
01586 for (int r = 0; r < rows; r++)
01587 for (int c = 0; c < cols; c++)
01588 {
01589 Value v1 = a1.element (c, r);
01590 Value v2 = a1.element (c, r);
01591 if (v1.isArray() && v2.isArray())
01592 twoArrayWalk (v1, v2, res, func);
01593 else {
01594 func (this, res, v1, v2);
01595 if (res.format() == Value::fmt_None)
01596 res.setFormat (format (v1.format(), v2.format()));
01597 }
01598 }
01599 }
01600
01601 void ValueCalc::twoArrayWalk (QValueVector<Value> &a1,
01602 QValueVector<Value> &a2, Value &res, arrayWalkFunc func)
01603 {
01604 if (res.isError()) return;
01605 if (a1.count() != a2.count()) {
01606 res = Value::errorVALUE();
01607 return;
01608 }
01609 for (unsigned int i = 0; i < a1.count(); ++i)
01610 twoArrayWalk (a1[i], a2[i], res, func);
01611 }
01612
01613 arrayWalkFunc ValueCalc::awFunc (const QString &name)
01614 {
01615 if (awFuncs.count(name))
01616 return awFuncs[name];
01617 return 0;
01618 }
01619
01620 void ValueCalc::registerAwFunc (const QString &name, arrayWalkFunc func)
01621 {
01622 awFuncs[name] = func;
01623 }
01624
01625
01626
01627 Value ValueCalc::sum (const Value &range, bool full)
01628 {
01629 Value res;
01630 arrayWalk (range, res, awFunc (full ? "suma" : "sum"), 0);
01631 return res;
01632 }
01633
01634 Value ValueCalc::sum (QValueVector<Value> range, bool full)
01635 {
01636 Value res;
01637 arrayWalk (range, res, awFunc (full ? "suma" : "sum"), 0);
01638 return res;
01639 }
01640
01641
01642 Value ValueCalc::sumsq (const Value &range, bool full)
01643 {
01644 Value res;
01645 arrayWalk (range, res, awFunc (full ? "sumsqa" : "sumsq"), 0);
01646 return res;
01647 }
01648
01649 Value ValueCalc::sumIf (const Value &range,
01650 const Value &checkRange, const Condition &cond)
01651 {
01652 if (!range.isArray())
01653 {
01654 if (matches (cond, checkRange.element (0, 0)))
01655 return converter->asNumeric (range);
01656 return Value (0.0);
01657 }
01658
01659
01660 Value res;
01661
01662 unsigned int rows = range.rows ();
01663 unsigned int cols = range.columns ();
01664 for (unsigned int r = 0; r < rows; r++)
01665 for (unsigned int c = 0; c < cols; c++)
01666 {
01667 Value v = range.element (c, r);
01668 Value newcheck = v;
01669 if ((c < checkRange.columns()) && (r < checkRange.rows()))
01670 newcheck = checkRange.element (c, r);
01671
01672 if (v.isArray())
01673 res = add (res, sumIf (v, newcheck, cond));
01674 else
01675 if (matches (cond, newcheck))
01676 res = add (res, v);
01677 }
01678
01679 return res;
01680 }
01681
01682 int ValueCalc::count (const Value &range, bool full)
01683 {
01684 Value res = 0;
01685 arrayWalk (range, res, awFunc (full ? "counta" : "count"), 0);
01686 return converter->asInteger (res).asInteger ();
01687 }
01688
01689 int ValueCalc::count (QValueVector<Value> range, bool full)
01690 {
01691 Value res = 0;
01692 arrayWalk (range, res, awFunc (full ? "counta" : "count"), 0);
01693 return converter->asInteger (res).asInteger ();
01694 }
01695
01696 int ValueCalc::countIf (const Value &range, const Condition &cond)
01697 {
01698 if (!range.isArray())
01699 {
01700 if (matches (cond, range))
01701 return range.isEmpty() ? 0 : 1;
01702 return 0;
01703 }
01704
01705 int res = 0;
01706
01707 int cols = range.columns ();
01708 int rows = range.rows ();
01709 for (int r = 0; r < rows; r++)
01710 for (int c = 0; c < cols; c++)
01711 {
01712 Value v = range.element (c, r);
01713
01714 if (v.isArray())
01715 res += countIf (v, cond);
01716 else
01717 if (matches (cond, v))
01718 res++;
01719 }
01720
01721 return res;
01722 }
01723
01724 Value ValueCalc::avg (const Value &range, bool full)
01725 {
01726 int cnt = count (range, full);
01727 if (cnt)
01728 return div (sum (range, full), cnt);
01729 return Value (0.0);
01730 }
01731
01732 Value ValueCalc::avg (QValueVector<Value> range, bool full)
01733 {
01734 int cnt = count (range, full);
01735 if (cnt)
01736 return div (sum (range, full), cnt);
01737 return Value (0.0);
01738 }
01739
01740 Value ValueCalc::max (const Value &range, bool full)
01741 {
01742 Value res;
01743 arrayWalk (range, res, awFunc (full ? "maxa" : "max"), 0);
01744 return res;
01745 }
01746
01747 Value ValueCalc::max (QValueVector<Value> range, bool full)
01748 {
01749 Value res;
01750 arrayWalk (range, res, awFunc (full ? "maxa" : "max"), 0);
01751 return res;
01752 }
01753
01754 Value ValueCalc::min (const Value &range, bool full)
01755 {
01756 Value res;
01757 arrayWalk (range, res, awFunc (full ? "mina" : "min"), 0);
01758 return res;
01759 }
01760
01761 Value ValueCalc::min (QValueVector<Value> range, bool full)
01762 {
01763 Value res;
01764 arrayWalk (range, res, awFunc (full ? "mina" : "min"), 0);
01765 return res;
01766 }
01767
01768 Value ValueCalc::product (const Value &range, Value init,
01769 bool full)
01770 {
01771 Value res = init;
01772 if (isZero (init))
01773 {
01774 if (count (range, full) == 0)
01775 return init;
01776 res = 1.0;
01777 }
01778 arrayWalk (range, res, awFunc (full ? "proda" : "prod"), 0);
01779 return res;
01780 }
01781
01782 Value ValueCalc::product (QValueVector<Value> range,
01783 Value init, bool full)
01784 {
01785 Value res = init;
01786 if (isZero (init))
01787 {
01788 if (count (range, full) == 0)
01789 return init;
01790 res = 1.0;
01791 }
01792 arrayWalk (range, res, awFunc (full ? "proda" : "prod"), 0);
01793 return res;
01794 }
01795
01796 Value ValueCalc::stddev (const Value &range, bool full)
01797 {
01798 return stddev (range, avg (range, full), full);
01799 }
01800
01801 Value ValueCalc::stddev (const Value &range, Value avg,
01802 bool full)
01803 {
01804 Value res;
01805 int cnt = count (range, full);
01806 arrayWalk (range, res, awFunc (full ? "devsqa" : "devsq"), avg);
01807 return sqrt (div (res, cnt-1));
01808 }
01809
01810 Value ValueCalc::stddev (QValueVector<Value> range, bool full)
01811 {
01812 return stddev (range, avg (range, full), full);
01813 }
01814
01815 Value ValueCalc::stddev (QValueVector<Value> range,
01816 Value avg, bool full)
01817 {
01818 Value res;
01819 int cnt = count (range, full);
01820 arrayWalk (range, res, awFunc (full ? "devsqa" : "devsq"), avg);
01821 return sqrt (div (res, cnt-1));
01822 }
01823
01824 Value ValueCalc::stddevP (const Value &range, bool full)
01825 {
01826 return stddevP (range, avg (range, full), full);
01827 }
01828
01829 Value ValueCalc::stddevP (const Value &range, Value avg,
01830 bool full)
01831 {
01832 Value res;
01833 int cnt = count (range, full);
01834 arrayWalk (range, res, awFunc (full ? "devsqa" : "devsq"), avg);
01835 return sqrt (div (res, cnt));
01836 }
01837
01838 Value ValueCalc::stddevP (QValueVector<Value> range, bool full)
01839 {
01840 return stddevP (range, avg (range, full), full);
01841 }
01842
01843 Value ValueCalc::stddevP (QValueVector<Value> range,
01844 Value avg, bool full)
01845 {
01846 Value res;
01847 int cnt = count (range, full);
01848 arrayWalk (range, res, awFunc (full ? "devsqa" : "devsq"), avg);
01849 return sqrt (div (res, cnt));
01850 }
01851
01852 Value::Format ValueCalc::format (Value::Format a,
01853 Value::Format b)
01854 {
01855 if ((a == Value::fmt_None) || (a == Value::fmt_Boolean))
01856 return b;
01857 return a;
01858 }
01859
01860
01861
01862
01863 void ValueCalc::getCond (Condition &cond, Value val)
01864 {
01865
01866
01867 if (!val.isString()) {
01868 cond.comp = isEqual;
01869 cond.type = numeric;
01870 cond.value = converter->asFloat (val).asFloat();
01871 return;
01872 }
01873 QString text = converter->asString (val).asString();
01874 cond.comp = isEqual;
01875 text = text.stripWhiteSpace();
01876
01877 if ( text.startsWith( "<=" ) )
01878 {
01879 cond.comp = lessEqual;
01880 text = text.remove( 0, 2 );
01881 }
01882 else if ( text.startsWith( ">=" ) )
01883 {
01884 cond.comp = greaterEqual;
01885 text = text.remove( 0, 2 );
01886 }
01887 else if ( text.startsWith( "!=" ) || text.startsWith( "<>" ) )
01888 {
01889 cond.comp = notEqual;
01890 text = text.remove( 0, 2 );
01891 }
01892 else if ( text.startsWith( "==" ) )
01893 {
01894 cond.comp = isEqual;
01895 text = text.remove( 0, 2 );
01896 }
01897 else if ( text.startsWith( "<" ) )
01898 {
01899 cond.comp = isLess;
01900 text = text.remove( 0, 1 );
01901 }
01902 else if ( text.startsWith( ">" ) )
01903 {
01904 cond.comp = isGreater;
01905 text = text.remove( 0, 1 );
01906 }
01907 else if ( text.startsWith( "=" ) )
01908 {
01909 cond.comp = isEqual;
01910 text = text.remove( 0, 1 );
01911 }
01912
01913 text = text.stripWhiteSpace();
01914
01915 bool ok = false;
01916 double d = text.toDouble( &ok );
01917 if ( ok )
01918 {
01919 cond.type = numeric;
01920 cond.value = d;
01921 }
01922 else
01923 {
01924 cond.type = string;
01925 cond.stringValue = text;
01926 }
01927 }
01928
01929 bool ValueCalc::matches (const Condition &cond, Value val)
01930 {
01931 if (val.isEmpty())
01932 return false;
01933 if (cond.type == numeric) {
01934 double d = converter->asFloat (val).asFloat();
01935 switch ( cond.comp )
01936 {
01937 case isEqual:
01938 if (approxEqual (d, cond.value)) return true;
01939 break;
01940
01941 case isLess:
01942 if (d < cond.value) return true;
01943 break;
01944
01945 case isGreater:
01946 if (d > cond.value) return true;
01947 break;
01948
01949 case lessEqual:
01950 if (d <= cond.value) return true;
01951 break;
01952
01953 case greaterEqual:
01954 if (d >= cond.value) return true;
01955 break;
01956
01957 case notEqual:
01958 if (d != cond.value) return true;
01959 break;
01960 }
01961 } else {
01962 QString d = converter->asString (val).asString();
01963 switch ( cond.comp )
01964 {
01965 case isEqual:
01966 if (d == cond.stringValue) return true;
01967 break;
01968
01969 case isLess:
01970 if (d < cond.stringValue) return true;
01971 break;
01972
01973 case isGreater:
01974 if (d > cond.stringValue) return true;
01975 break;
01976
01977 case lessEqual:
01978 if (d <= cond.stringValue) return true;
01979 break;
01980
01981 case greaterEqual:
01982 if (d >= cond.stringValue) return true;
01983 break;
01984
01985 case notEqual:
01986 if (d != cond.stringValue) return true;
01987 break;
01988 }
01989 }
01990 return false;
01991 }
01992