kspread

valuecalc.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
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 // Array-walk functions registered on ValueCalc object
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       // convert to number, so that we don't return string/bool
00086       res = c->conv()->asNumeric (val);
00087     else
00088       if (c->greater (val, res))
00089         // convert to number, so that we don't return string/bool
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       // convert to number, so that we don't return string/bool
00107       res = c->conv()->asNumeric (val);
00108     else
00109       if (c->lower (val, res))
00110         // convert to number, so that we don't return string/bool
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 // sum of squares of deviations, used to compute standard deviation
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 // sum of squares of deviations, used to compute standard deviation
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 // ****** ValueCalc ******
00152 // ***********************
00153 
00154 ValueCalc::ValueCalc (ValueConverter* c): converter( c )
00155 {
00156   // initialize the random number generator
00157   srand (time (0));
00158   
00159   // register array-walk functions
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   // operation on two dates should produce a number
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   // operation on two dates should produce a number
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   // operation on two dates should produce a number
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   // operation on two dates should produce a number
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     // the following adjustments are needed by OpenFormula:
00278     // can't simply use fixed increases/decreases, because the implementation
00279     // of fmod may differ on various platforms, and we should always return
00280     // the same results ...
00281     if ((bb > 0) && (aa < 0))  // result must be positive here
00282       while (m < 0) m += bb;
00283     if (bb < 0)  // result must be negative here, but not lower than bb
00284     {
00285       // bb is negative, hence the following two are correct
00286       while (m < bb) m -= bb;  // same as m+=fabs(bb)
00287       while (m > 0) m += bb;   // same as m-=fabs(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   // operation on date(s) should produce a number
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   // operation on date(s) should produce a number
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  * Helper function to avoid problems with rounding floating point
00423  * values. Idea for this kind of solution taken from Openoffice.
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   // shift in one direction, round, shift back
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   // shift in one direction, round, shift back
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   // shift in one direction, round, shift back
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   // retun PI in double-precision
00600   // if arbitrary precision gets in, this should be extended to return
00601   // more if need be
00602   return Value (M_PI);
00603 }
00604 
00605 Value ValueCalc::eps ()
00606 {
00607   // #### This should adjust according to the actual number system used
00608   // (float, double, long double, ...)
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   // we can simply use integers - no one is going to compute factorial of
00625   // anything bigger than 2^32
00626   return fact (converter->asInteger (which).asInteger());
00627 }
00628 
00629 Value ValueCalc::fact (const Value &which,
00630     const Value &end)
00631 {
00632   // we can simply use integers - no one is going to compute factorial of
00633   // anything bigger than 2^32
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   // no multiplication if val==end
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   // Euler's GCD algorithm
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())  // GCD is zero for some weird reason
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   // constant * exp(-(x * x) / 2.0);
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 // this is a weird function
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 // this is a weird function
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 //helper for GetGamma and GetLogGamma
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;   // sqrt(2*PI)
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   // double g = exp(a+b) / den;
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       // return pow( dx, dgamma ) * exp( -dx ) * t / g;
01263       return Value (::exp( dgamma * ::log(dx) - dx - a - b ) * t * den);
01264     }
01265   }
01266 
01267   return Value (1.0);             // should not happen ...
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     // 1.0 - pow (1.0-_x, _beta)
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  * The code for calculating Bessel functions is taken
01353  * from CCMATH, a mathematics library source.code.
01354  *
01355  * Original copyright follows:
01356  *
01357  *  Copyright (C)  2000   Daniel A. Atkinson    All rights reserved.
01358  *  This code may be redistributed under the terms of the GNU library
01359  *  public license (LGPL).
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 /* ---------- end of CCMATH code ---------- */
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 // sum of squares
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   //if we are here, we have an array
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))  // special handling of a zero, due to excel-compat
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))  // special handling of a zero, due to excel-compat
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   // not a string - we simply take it as a numeric value
01866   // that also handles floats, logical values, date/time and such
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 
KDE Home | KDE Accessibility Home | Description of Access Keys