kspread

kspread_functions_statistical.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998-2002 The KSpread Team
3 www.koffice.org/kspread
4 Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22// built-in statistical functions
23
24#include "functions.h"
25#include "valuecalc.h"
26#include "valueconverter.h"
27
28// needed for MODE
29#include <tqmap.h>
30
31using namespace KSpread;
32
33// prototypes (sorted!)
34Value func_arrang (valVector args, ValueCalc *calc, FuncExtra *);
35Value func_average (valVector args, ValueCalc *calc, FuncExtra *);
36Value func_averagea (valVector args, ValueCalc *calc, FuncExtra *);
37Value func_avedev (valVector args, ValueCalc *calc, FuncExtra *);
38Value func_betadist (valVector args, ValueCalc *calc, FuncExtra *);
39Value func_bino (valVector args, ValueCalc *calc, FuncExtra *);
40Value func_chidist (valVector args, ValueCalc *calc, FuncExtra *);
41Value func_combin (valVector args, ValueCalc *calc, FuncExtra *);
42Value func_confidence (valVector args, ValueCalc *calc, FuncExtra *);
43Value func_correl_pop (valVector args, ValueCalc *calc, FuncExtra *);
44Value func_covar (valVector args, ValueCalc *calc, FuncExtra *);
45Value func_devsq (valVector args, ValueCalc *calc, FuncExtra *);
46Value func_devsqa (valVector args, ValueCalc *calc, FuncExtra *);
47Value func_expondist (valVector args, ValueCalc *calc, FuncExtra *);
48Value func_fdist (valVector args, ValueCalc *calc, FuncExtra *);
49Value func_fisher (valVector args, ValueCalc *calc, FuncExtra *);
50Value func_fisherinv (valVector args, ValueCalc *calc, FuncExtra *);
51Value func_gammadist (valVector args, ValueCalc *calc, FuncExtra *);
52Value func_gammaln (valVector args, ValueCalc *calc, FuncExtra *);
53Value func_gauss (valVector args, ValueCalc *calc, FuncExtra *);
54Value func_geomean (valVector args, ValueCalc *calc, FuncExtra *);
55Value func_harmean (valVector args, ValueCalc *calc, FuncExtra *);
56Value func_hypgeomdist (valVector args, ValueCalc *calc, FuncExtra *);
57Value func_kurtosis_est (valVector args, ValueCalc *calc, FuncExtra *);
58Value func_kurtosis_pop (valVector args, ValueCalc *calc, FuncExtra *);
59Value func_large (valVector args, ValueCalc *calc, FuncExtra *);
60Value func_loginv (valVector args, ValueCalc *calc, FuncExtra *);
61Value func_lognormdist (valVector args, ValueCalc *calc, FuncExtra *);
62Value func_median (valVector args, ValueCalc *calc, FuncExtra *);
63Value func_mode (valVector args, ValueCalc *calc, FuncExtra *);
64Value func_negbinomdist (valVector args, ValueCalc *calc, FuncExtra *);
65Value func_normdist (valVector args, ValueCalc *calc, FuncExtra *);
66Value func_norminv (valVector args, ValueCalc *calc, FuncExtra *);
67Value func_normsinv (valVector args, ValueCalc *calc, FuncExtra *);
68Value func_phi (valVector args, ValueCalc *calc, FuncExtra *);
69Value func_poisson (valVector args, ValueCalc *calc, FuncExtra *);
70Value func_skew_est (valVector args, ValueCalc *calc, FuncExtra *);
71Value func_skew_pop (valVector args, ValueCalc *calc, FuncExtra *);
72Value func_small (valVector args, ValueCalc *calc, FuncExtra *);
73Value func_standardize (valVector args, ValueCalc *calc, FuncExtra *);
74Value func_stddev (valVector args, ValueCalc *calc, FuncExtra *);
75Value func_stddeva (valVector args, ValueCalc *calc, FuncExtra *);
76Value func_stddevp (valVector args, ValueCalc *calc, FuncExtra *);
77Value func_stddevpa (valVector args, ValueCalc *calc, FuncExtra *);
78Value func_stdnormdist (valVector args, ValueCalc *calc, FuncExtra *);
79Value func_sumproduct (valVector args, ValueCalc *calc, FuncExtra *);
80Value func_sumx2py2 (valVector args, ValueCalc *calc, FuncExtra *);
81Value func_sumx2my2 (valVector args, ValueCalc *calc, FuncExtra *);
82Value func_sumxmy2 (valVector args, ValueCalc *calc, FuncExtra *);
83Value func_tdist (valVector args, ValueCalc *calc, FuncExtra *);
84Value func_variance (valVector args, ValueCalc *calc, FuncExtra *);
85Value func_variancea (valVector args, ValueCalc *calc, FuncExtra *);
86Value func_variancep (valVector args, ValueCalc *calc, FuncExtra *);
87Value func_variancepa (valVector args, ValueCalc *calc, FuncExtra *);
88Value func_weibull (valVector args, ValueCalc *calc, FuncExtra *);
89
90typedef TQValueList<double> List;
91
92// registers all statistical functions
93void RegisterStatisticalFunctions()
94{
95 FunctionRepository* repo = FunctionRepository::self();
96 Function *f;
97
98 f = new Function ("AVEDEV", func_avedev);
99 f->setParamCount (1, -1);
100 f->setAcceptArray ();
101 repo->add (f);
102 f = new Function ("AVERAGE", func_average);
103 f->setParamCount (1, -1);
104 f->setAcceptArray ();
105 repo->add (f);
106 f = new Function ("AVERAGEA", func_averagea);
107 f->setParamCount (1, -1);
108 f->setAcceptArray ();
109 repo->add (f);
110 f = new Function ("BETADIST", func_betadist);
111 f->setParamCount (3, 5);
112 repo->add (f);
113 f = new Function ("BINO", func_bino);
114 f->setParamCount (3);
115 repo->add (f);
116 f = new Function ("CHIDIST", func_chidist);
117 f->setParamCount (2);
118 repo->add (f);
119 f = new Function ("COMBIN", func_combin);
120 f->setParamCount (2);
121 repo->add (f);
122 f = new Function ("CONFIDENCE", func_confidence);
123 f->setParamCount (3);
124 repo->add (f);
125 f = new Function ("CORREL", func_correl_pop);
126 f->setParamCount (2);
127 f->setAcceptArray ();
128 repo->add (f);
129 f = new Function ("COVAR", func_covar);
130 f->setParamCount (2);
131 f->setAcceptArray ();
132 repo->add (f);
133 f = new Function ("DEVSQ", func_devsq);
134 f->setParamCount (1, -1);
135 f->setAcceptArray ();
136 repo->add (f);
137 f = new Function ("DEVSQA", func_devsqa);
138 f->setParamCount (1, -1);
139 f->setAcceptArray ();
140 repo->add (f);
141 f = new Function ("EXPONDIST", func_expondist);
142 f->setParamCount (3);
143 repo->add (f);
144 f = new Function ("FDIST", func_fdist);
145 f->setParamCount (3);
146 repo->add (f);
147 f = new Function ("FISHER", func_fisher);
148 repo->add (f);
149 f = new Function ("FISHERINV", func_fisherinv);
150 repo->add (f);
151 f = new Function ("GAMMADIST", func_gammadist);
152 f->setParamCount (4);
153 repo->add (f);
154 f = new Function ("GAMMALN", func_gammaln);
155 repo->add (f);
156 f = new Function ("GAUSS", func_gauss);
157 repo->add (f);
158 f = new Function ("GEOMEAN", func_geomean);
159 f->setParamCount (1, -1);
160 f->setAcceptArray ();
161 repo->add (f);
162 f = new Function ("HARMEAN", func_harmean);
163 f->setParamCount (1, -1);
164 f->setAcceptArray ();
165 repo->add (f);
166 f = new Function ("HYPGEOMDIST", func_hypgeomdist);
167 f->setParamCount (4);
168 repo->add (f);
169 f = new Function ("INVBINO", func_bino); // same as BINO, for 1.4 compat
170 repo->add (f);
171 f = new Function ("KURT", func_kurtosis_est);
172 f->setParamCount (1, -1);
173 f->setAcceptArray ();
174 repo->add (f);
175 f = new Function ("KURTP", func_kurtosis_pop);
176 f->setParamCount (1, -1);
177 f->setAcceptArray ();
178 repo->add (f);
179 f = new Function ("LARGE", func_large);
180 f->setParamCount (2);
181 f->setAcceptArray ();
182 repo->add (f);
183 f = new Function ("LOGINV", func_loginv);
184 f->setParamCount (3);
185 repo->add (f);
186 f = new Function ("LOGNORMDIST", func_lognormdist);
187 f->setParamCount (3);
188 repo->add (f);
189 f = new Function ("MEDIAN", func_median);
190 f->setParamCount (1, -1);
191 f->setAcceptArray ();
192 repo->add (f);
193 f = new Function ("MODE", func_mode);
194 f->setParamCount (1, -1);
195 f->setAcceptArray ();
196 repo->add (f);
197 f = new Function ("NEGBINOMDIST", func_negbinomdist);
198 f->setParamCount (3);
199 repo->add (f);
200 f = new Function ("NORMDIST", func_normdist);
201 f->setParamCount (4);
202 repo->add (f);
203 f = new Function ("NORMINV", func_norminv);
204 f->setParamCount (3);
205 repo->add (f);
206 f = new Function ("NORMSDIST", func_stdnormdist);
207 repo->add (f);
208 f = new Function ("NORMSINV", func_normsinv);
209 repo->add (f);
210 f = new Function ("PEARSON", func_correl_pop);
211 f->setParamCount (2);
212 f->setAcceptArray ();
213 repo->add (f);
214 f = new Function ("PERMUT", func_arrang);
215 f->setParamCount (2);
216 repo->add (f);
217 f = new Function ("PHI", func_phi);
218 repo->add (f);
219 f = new Function ("POISSON", func_poisson);
220 f->setParamCount (3);
221 repo->add (f);
222 f = new Function ("SKEW", func_skew_est);
223 f->setParamCount (1, -1);
224 f->setAcceptArray ();
225 repo->add (f);
226 f = new Function ("SKEWP", func_skew_pop);
227 f->setParamCount (1, -1);
228 f->setAcceptArray ();
229 repo->add (f);
230 f = new Function ("SMALL", func_small);
231 f->setParamCount (2);
232 f->setAcceptArray ();
233 repo->add (f);
234 f = new Function ("STANDARDIZE", func_standardize);
235 f->setParamCount (3);
236 repo->add (f);
237 f = new Function ("STDEV", func_stddev);
238 f->setParamCount (1, -1);
239 f->setAcceptArray ();
240 repo->add (f);
241 f = new Function ("STDEVA", func_stddeva);
242 f->setParamCount (1, -1);
243 f->setAcceptArray ();
244 repo->add (f);
245 f = new Function ("STDEVP", func_stddevp);
246 f->setParamCount (1, -1);
247 f->setAcceptArray ();
248 repo->add (f);
249 f = new Function ("STDEVPA", func_stddevpa);
250 f->setParamCount (1, -1);
251 f->setAcceptArray ();
252 repo->add (f);
253 f = new Function ("SUM2XMY", func_sumxmy2);
254 f->setParamCount (2);
255 f->setAcceptArray ();
256 repo->add (f);
257 f = new Function ("SUMPRODUCT", func_sumproduct);
258 f->setParamCount (2);
259 f->setAcceptArray ();
260 repo->add (f);
261 f = new Function ("SUMX2PY2", func_sumx2py2);
262 f->setParamCount (2);
263 f->setAcceptArray ();
264 repo->add (f);
265 f = new Function ("SUMX2MY2", func_sumx2my2);
266 f->setParamCount (2);
267 f->setAcceptArray ();
268 repo->add (f);
269 f = new Function ("TDIST", func_tdist);
270 f->setParamCount (3);
271 repo->add (f);
272 f = new Function ("VARIANCE", func_variance);
273 f->setParamCount (1, -1);
274 f->setAcceptArray ();
275 repo->add (f);
276 f = new Function ("VAR", func_variance);
277 f->setParamCount (1, -1);
278 f->setAcceptArray ();
279 repo->add (f);
280 f = new Function ("VARP", func_variancep);
281 f->setParamCount (1, -1);
282 f->setAcceptArray ();
283 repo->add (f);
284 f = new Function ("VARA", func_variancea);
285 f->setParamCount (1, -1);
286 f->setAcceptArray ();
287 repo->add (f);
288 f = new Function ("VARPA", func_variancepa);
289 f->setParamCount (1, -1);
290 f->setAcceptArray ();
291 repo->add (f);
292 f = new Function ("WEIBULL", func_weibull);
293 f->setParamCount (4);
294 repo->add (f);
295}
296
297// array-walk functions used in this file
298
299void awSkew (ValueCalc *c, Value &res, Value val, Value p)
300{
301 Value avg = p.element (0, 0);
302 Value stdev = p.element (1, 0);
303 // (val - avg) / stddev
304 Value d = c->div (c->sub (val, avg), stdev);
305 // res += d*d*d
306 res = c->add (res, c->mul (d, c->mul (d, d)));
307}
308
309void awSumInv (ValueCalc *c, Value &res, Value val, Value)
310{
311 // res += 1/value
312 res = c->add (res, c->div (1.0, val));
313}
314
315void awAveDev (ValueCalc *c, Value &res, Value val,
316 Value p)
317{
318 // res += abs (val - p)
319 res = c->add (res, c->abs (c->sub (val, p)));
320}
321
322void awKurtosis (ValueCalc *c, Value &res, Value val,
323 Value p)
324{
325 Value avg = p.element (0, 0);
326 Value stdev = p.element (1, 0);
327 //d = (val - avg ) / stdev
328 Value d = c->div (c->sub (val, avg), stdev);
329 // res += d^4
330 res = c->add (res, c->pow (d, 4));
331}
332
333
334Value func_skew_est (valVector args, ValueCalc *calc, FuncExtra *)
335{
336 int number = calc->count (args);
337 Value avg = calc->avg (args);
338 if (number < 3)
339 return Value::errorVALUE();
340
341 Value res = calc->stddev (args, avg);
342 if (res.isZero())
343 return Value::errorVALUE();
344
345 Value params (2, 1);
346 params.setElement (0, 0, avg);
347 params.setElement (1, 0, res);
348 Value tskew;
349 calc->arrayWalk (args, tskew, awSkew, params);
350
351 // ((tskew * number) / (number-1)) / (number-2)
352 return calc->div (calc->div (calc->mul (tskew, number), number-1), number-2);
353}
354
355Value func_skew_pop (valVector args, ValueCalc *calc, FuncExtra *)
356{
357 int number = calc->count (args);
358 Value avg = calc->avg (args);
359 if (number < 1)
360 return Value::errorVALUE();
361
362 Value res = calc->stddevP (args, avg);
363 if (res.isZero())
364 return Value::errorVALUE();
365
366 Value params (2, 1);
367 params.setElement (0, 0, avg);
368 params.setElement (1, 0, res);
369 Value tskew;
370 calc->arrayWalk (args, tskew, awSkew, params);
371
372 // tskew / number
373 return calc->div (tskew, number);
374}
375
376class ContentSheet : public TQMap<double, int> {};
377
378void func_mode_helper (Value range, ValueCalc *calc, ContentSheet &sh)
379{
380 if (!range.isArray())
381 {
382 double d = calc->conv()->asFloat (range).asFloat();
383 sh[d]++;
384 return;
385 }
386
387 for (unsigned int row = 0; row < range.rows(); ++row)
388 for (unsigned int col = 0; col < range.columns(); ++col) {
389 Value v = range.element (col, row);
390 if (v.isArray())
391 func_mode_helper (v, calc, sh);
392 else {
393 double d = calc->conv()->asFloat (v).asFloat();
394 sh[d]++;
395 }
396 }
397}
398
399Value func_mode (valVector args, ValueCalc *calc, FuncExtra *)
400{
401 // does NOT support anything other than doubles !!!
402 ContentSheet sh;
403 for (unsigned int i = 0; i < args.count(); ++i)
404 func_mode_helper (args[i], calc, sh);
405
406 // retrieve value with max.count
407 int maxcount = 0;
408 double max = 0.0;
409 ContentSheet::iterator it;
410 for (it = sh.begin(); it != sh.end(); ++it)
411 if (it.data() > maxcount) {
412 max = it.key();
413 maxcount = it.data();
414 }
415 return Value (max);
416}
417
418Value func_covar_helper (Value range1, Value range2,
419 ValueCalc *calc, Value avg1, Value avg2)
420{
421 // two arrays -> cannot use arrayWalk
422 if ((!range1.isArray()) && (!range2.isArray()))
423 // (v1-E1)*(v2-E2)
424 return calc->mul (calc->sub (range1, avg1), calc->sub (range2, avg2));
425
426 int rows = range1.rows();
427 int cols = range1.columns();
428 int rows2 = range2.rows();
429 int cols2 = range2.columns();
430 if ((rows != rows2) || (cols != cols2))
431 return Value::errorVALUE();
432
433 Value result = 0.0;
434 for (int row = 0; row < rows; ++row)
435 for (int col = 0; col < cols; ++col) {
436 Value v1 = range1.element (col, row);
437 Value v2 = range2.element (col, row);
438 if (v1.isArray() || v2.isArray())
439 result = calc->add (result,
440 func_covar_helper (v1, v2, calc, avg1, avg2));
441 else
442 // result += (v1-E1)*(v2-E2)
443 result = calc->add (result, calc->mul (calc->sub (v1, avg1),
444 calc->sub (v2, avg2)));
445 }
446
447 return result;
448}
449
450Value func_covar (valVector args, ValueCalc *calc, FuncExtra *)
451{
452 Value avg1 = calc->avg (args[0]);
453 Value avg2 = calc->avg (args[1]);
454 int number = calc->count (args[0]);
455 int number2 = calc->count (args[1]);
456
457 if (number2 <= 0 || number2 != number)
458 return Value::errorVALUE();
459
460 Value covar = func_covar_helper (args[0], args[1], calc, avg1, avg2);
461 return calc->div (covar, number);
462}
463
464Value func_correl_pop (valVector args, ValueCalc *calc, FuncExtra *)
465{
466 Value covar = func_covar (args, calc, 0);
467 Value stdevp1 = calc->stddevP (args[0]);
468 Value stdevp2 = calc->stddevP (args[1]);
469
470 if (calc->isZero (stdevp1) || calc->isZero (stdevp2))
471 return Value::errorDIV0();
472
473 // covar / (stdevp1 * stdevp2)
474 return calc->div (covar, calc->mul (stdevp1, stdevp2));
475}
476
477void func_array_helper (Value range, ValueCalc *calc,
478 List &array, int &number)
479{
480 if (!range.isArray())
481 {
482 array << calc->conv()->asFloat (range).asFloat();
483 ++number;
484 return;
485 }
486
487 for (unsigned int row = 0; row < range.rows(); ++row)
488 for (unsigned int col = 0; col < range.columns(); ++col) {
489 Value v = range.element (col, row);
490 if (v.isArray ())
491 func_array_helper (v, calc, array, number);
492 else {
493 array << calc->conv()->asFloat (v).asFloat();
494 ++number;
495 }
496 }
497}
498
499Value func_large (valVector args, ValueCalc *calc, FuncExtra *)
500{
501 // does NOT support anything other than doubles !!!
502 int k = calc->conv()->asInteger (args[1]).asInteger();
503 if ( k < 1 )
504 return false;
505
506 List array;
507 int number = 1;
508
509 func_array_helper (args[0], calc, array, number);
510
511 if ( k > number )
512 return Value::errorVALUE();
513
514 qHeapSort (array);
515 double d = *array.at (number - k - 1);
516 return Value (d);
517}
518
519Value func_small (valVector args, ValueCalc *calc, FuncExtra *)
520{
521 // does NOT support anything other than doubles !!!
522 int k = calc->conv()->asInteger (args[1]).asInteger();
523 if ( k < 1 )
524 return false;
525
526 List array;
527 int number = 1;
528
529 func_array_helper (args[0], calc, array, number);
530
531 if ( k > number )
532 return Value::errorVALUE();
533
534 qHeapSort (array);
535 double d = *array.at (k - 1);
536 return Value (d);
537}
538
539Value func_geomean (valVector args, ValueCalc *calc, FuncExtra *)
540{
541 Value count = calc->count (args);
542 Value prod = calc->product (args, 1.0);
543 if (calc->isZero (count))
544 return Value::errorDIV0();
545 return calc->pow (prod, calc->div (1.0, count));
546}
547
548Value func_harmean (valVector args, ValueCalc *calc, FuncExtra *)
549{
550 Value count = calc->count (args);
551 if (calc->isZero (count))
552 return Value::errorDIV0();
553 Value suminv;
554 calc->arrayWalk (args, suminv, awSumInv, 0);
555 return calc->div (suminv, count);
556}
557
558Value func_loginv (valVector args, ValueCalc *calc, FuncExtra *)
559{
560 Value p = args[0];
561 Value m = args[1];
562 Value s = args[2];
563
564 if (calc->lower (p, 0) || calc->greater (p, 1))
565 return Value::errorVALUE();
566
567 if (!calc->greater (s, 0))
568 return Value::errorVALUE();
569
570 Value result = 0.0;
571 if (calc->equal (p, 1)) //p==1
572 result = Value::errorVALUE();
573 else if (calc->greater (p, 0)) { //p>0
574 Value gaussInv = calc->gaussinv (p);
575 // exp (gaussInv * s + m)
576 result = calc->exp (calc->add (calc->mul (s, gaussInv), m));
577 }
578
579 return result;
580}
581
582Value func_devsq (valVector args, ValueCalc *calc, FuncExtra *)
583{
584 Value res;
585 calc->arrayWalk (args, res, calc->awFunc ("devsq"), calc->avg (args, false));
586 return res;
587}
588
589Value func_devsqa (valVector args, ValueCalc *calc, FuncExtra *)
590{
591 Value res;
592 calc->arrayWalk (args, res, calc->awFunc ("devsqa"), calc->avg (args));
593 return res;
594}
595
596Value func_kurtosis_est (valVector args, ValueCalc *calc, FuncExtra *)
597{
598 int count = calc->count (args);
599 if (count < 4)
600 return Value::errorVALUE();
601
602 Value avg = calc->avg (args);
603 Value devsq;
604 calc->arrayWalk (args, devsq, calc->awFunc ("devsqa"), avg);
605
606 if (devsq.isZero ())
607 return Value::errorDIV0();
608
609 Value params (2, 1);
610 params.setElement (0, 0, avg);
611 params.setElement (1, 0, devsq);
612 Value x4;
613 calc->arrayWalk (args, x4, awKurtosis, params);
614
615 double den = (double) (count - 2) * (count - 3);
616 double nth = (double) count * (count + 1) / ((count - 1) * den);
617 double t = 3.0 * (count - 1) * (count - 1) / den;
618
619 // res = x4 * nth - t
620 return calc->sub (calc->mul (x4, nth), t);
621}
622
623Value func_kurtosis_pop (valVector args, ValueCalc *calc, FuncExtra *)
624{
625 int count = calc->count (args);
626 if (count < 4)
627 return Value::errorVALUE();
628
629 Value avg = calc->avg (args);
630 Value devsq;
631 calc->arrayWalk (args, devsq, calc->awFunc ("devsqa"), avg);
632
633 if (devsq.isZero ())
634 return Value::errorDIV0();
635
636 Value params (2, 1);
637 params.setElement (0, 0, avg);
638 params.setElement (1, 0, devsq);
639 Value x4;
640 calc->arrayWalk (args, x4, awKurtosis, params);
641
642 // x4 / count - 3
643 return calc->sub (calc->div (x4, count), 3);
644}
645
646Value func_standardize (valVector args, ValueCalc *calc, FuncExtra *)
647{
648 Value x = args[0];
649 Value m = args[1];
650 Value s = args[2];
651
652 if (!calc->greater (s, 0)) // s must be >0
653 return Value::errorVALUE();
654
655 // (x - m) / s
656 return calc->div (calc->sub (x, m), s);
657}
658
659Value func_hypgeomdist (valVector args, ValueCalc *calc, FuncExtra *)
660{
661 int x = calc->conv()->asInteger (args[0]).asInteger();
662 int n = calc->conv()->asInteger (args[1]).asInteger();
663 int M = calc->conv()->asInteger (args[2]).asInteger();
664 int N = calc->conv()->asInteger (args[3]).asInteger();
665
666 if ( x < 0 || n < 0 || M < 0 || N < 0 )
667 return Value::errorVALUE();
668
669 if ( x > M || n > N )
670 return Value::errorVALUE();
671
672 Value d1 = calc->combin (M, x);
673 Value d2 = calc->combin (N - M, n - x);
674 Value d3 = calc->combin (N, n);
675
676 // d1 * d2 / d3
677 return calc->div (calc->mul (d1, d2), d3);
678}
679
680Value func_negbinomdist (valVector args, ValueCalc *calc, FuncExtra *)
681{
682 int x = calc->conv()->asInteger (args[0]).asInteger();
683 int r = calc->conv()->asInteger (args[1]).asInteger();
684 Value p = args[2];
685
686 if ((x + r - 1) <= 0)
687 return Value::errorVALUE();
688 if (calc->lower (p, 0) || calc->greater (p, 1))
689 return Value::errorVALUE();
690
691 Value d1 = calc->combin (x + r - 1, r - 1);
692 // d2 = pow (p, r) * pow (1 - p, x)
693 Value d2 = calc->mul (calc->pow (p, r),
694 calc->pow (calc->sub (1, p), x));
695
696 return calc->mul (d1, d2);
697}
698
699// Function: permut
700Value func_arrang (valVector args, ValueCalc *calc, FuncExtra *)
701{
702 Value n = args[0];
703 Value m = args[1];
704 if (calc->lower (n, m)) // problem if n<m
705 return Value::errorVALUE();
706
707 if (calc->lower (m, 0)) // problem if m<0 (n>=m so that's okay)
708 return Value::errorVALUE();
709
710 // fact(n) / (fact(n-m)
711 return calc->fact (n, calc->sub (n, m));
712}
713
714// Function: average
715Value func_average (valVector args, ValueCalc *calc, FuncExtra *)
716{
717 return calc->avg (args, false);
718}
719
720// Function: averagea
721Value func_averagea (valVector args, ValueCalc *calc, FuncExtra *)
722{
723 return calc->avg (args);
724}
725
726// Function: avedev
727Value func_avedev (valVector args, ValueCalc *calc, FuncExtra *)
728{
729 Value result;
730 calc->arrayWalk (args, result, awAveDev, calc->avg (args));
731 return result;
732}
733
734// Function: median
735Value func_median (valVector args, ValueCalc *calc, FuncExtra *)
736{
737 // does NOT support anything other than doubles !!!
738 List array;
739 int number = 1;
740
741 for (unsigned int i = 0; i < args.count(); ++i)
742 func_array_helper (args[i], calc, array, number);
743
744 qHeapSort (array);
745 double d = *array.at (number / 2 + number % 2);
746 return Value (d);
747}
748
749// Function: variance
750Value func_variance (valVector args, ValueCalc *calc, FuncExtra *)
751{
752 int count = calc->count (args, false);
753 if (count < 2)
754 return Value::errorVALUE();
755
756 Value result = func_devsq (args, calc, 0);
757 return calc->div (result, count-1);
758}
759
760// Function: vara
761Value func_variancea (valVector args, ValueCalc *calc, FuncExtra *)
762{
763 int count = calc->count (args);
764 if (count < 2)
765 return Value::errorVALUE();
766
767 Value result = func_devsqa (args, calc, 0);
768 return calc->div (result, count-1);
769}
770
771// Function: varp
772Value func_variancep (valVector args, ValueCalc *calc, FuncExtra *)
773{
774 int count = calc->count (args, false);
775 if (count == 0)
776 return Value::errorVALUE();
777
778 Value result = func_devsq (args, calc, 0);
779 return calc->div (result, count);
780}
781
782// Function: varpa
783Value func_variancepa (valVector args, ValueCalc *calc, FuncExtra *)
784{
785 int count = calc->count (args);
786 if (count == 0)
787 return Value::errorVALUE();
788
789 Value result = func_devsqa (args, calc, 0);
790 return calc->div (result, count);
791}
792
793// Function: stddev
794Value func_stddev (valVector args, ValueCalc *calc, FuncExtra *)
795{
796 return calc->stddev (args, false);
797}
798
799// Function: stddeva
800Value func_stddeva (valVector args, ValueCalc *calc, FuncExtra *)
801{
802 return calc->stddev (args);
803}
804
805// Function: stddevp
806Value func_stddevp (valVector args, ValueCalc *calc, FuncExtra *)
807{
808 return calc->stddevP (args, false);
809}
810
811// Function: stddevpa
812Value func_stddevpa (valVector args, ValueCalc *calc, FuncExtra *)
813{
814 return calc->stddevP (args);
815}
816
817// Function: combin
818Value func_combin (valVector args, ValueCalc *calc, FuncExtra *)
819{
820 return calc->combin (args[0], args[1]);
821}
822
823// Function: bino
824Value func_bino (valVector args, ValueCalc *calc, FuncExtra *)
825{
826 Value n = args[0];
827 Value m = args[1];
828 Value comb = calc->combin (n, m);
829 Value prob = args[2];
830
831 if (calc->lower (prob,0) || calc->greater (prob,1))
832 return Value::errorVALUE();
833
834 // result = comb * pow (prob, m) * pow (1 - prob, n - m)
835 Value pow1 = calc->pow (prob, m);
836 Value pow2 = calc->pow (calc->sub (1, prob), calc->sub (n, m));
837 return calc->mul (comb, calc->mul (pow1, pow2));
838}
839
840// Function: phi
841Value func_phi (valVector args, ValueCalc *calc, FuncExtra *)
842//distribution function for a standard normal distribution
843{
844 return calc->phi (args[0]);
845}
846
847// Function: gauss
848Value func_gauss (valVector args, ValueCalc *calc, FuncExtra *)
849{
850 //returns the integral values of the standard normal cumulative distribution
851 return calc->gauss (args[0]);
852}
853
854// Function: gammadist
855Value func_gammadist (valVector args, ValueCalc *calc, FuncExtra *)
856{
857 Value x = args[0];
858 Value alpha = args[1];
859 Value beta = args[2];
860 int kum = calc->conv()->asInteger (args[3]).asInteger(); // 0 or 1
861
862 Value result;
863
864 if (calc->lower (x, 0.0) || (!calc->greater (alpha, 0.0)) ||
865 (!calc->greater (beta, 0.0)))
866 return Value::errorVALUE();
867
868 if (kum == 0) { //density
869 Value G = calc->GetGamma (alpha);
870 // result = pow (x, alpha - 1.0) / exp (x / beta) / pow (beta, alpha) / G
871 Value pow1 = calc->pow (x, calc->sub (alpha, 1.0));
872 Value pow2 = calc->exp (calc->div (x, beta));
873 Value pow3 = calc->pow (beta, alpha);
874 result = calc->div (calc->div (calc->div (pow1, pow2), pow3), G);
875 }
876 else
877 result = calc->GetGammaDist (x, alpha, beta);
878
879 return Value (result);
880}
881
882// Function: betadist
883Value func_betadist (valVector args, ValueCalc *calc, FuncExtra *)
884{
885 Value x = args[0];
886 Value alpha = args[1];
887 Value beta = args[2];
888
889 Value fA = 0.0;
890 Value fB = 1.0;
891 if (args.count() > 3) fA = args[3];
892 if (args.count() == 5) fB = args[4];
893
894 //x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0
895 if (calc->lower (x, fA) || calc->greater (x, fB) || calc->equal (fA, fB) ||
896 (!calc->greater (alpha, 0.0)) || (!calc->greater (beta, 0.0)))
897 return Value::errorVALUE();
898
899 // xx = (x - fA) / (fB - fA) // scaling
900 Value xx = calc->div (calc->sub (x, fA), calc->sub (fB, fA));
901
902 return calc->GetBeta (xx, alpha, beta);
903}
904
905// Function: fisher
906Value func_fisher (valVector args, ValueCalc *calc, FuncExtra *) {
907 //returns the Fisher transformation for x
908
909 // 0.5 * ln ((1.0 + fVal) / (1.0 - fVal))
910 Value fVal = args[0];
911 Value num = calc->div (calc->add (fVal, 1.0), calc->sub (1.0, fVal));
912 return calc->mul (calc->ln (num), 0.5);
913}
914
915// Function: fisherinv
916Value func_fisherinv (valVector args, ValueCalc *calc, FuncExtra *) {
917 //returns the inverse of the Fisher transformation for x
918
919 Value fVal = args[0];
920 // (exp (2.0 * fVal) - 1.0) / (exp (2.0 * fVal) + 1.0)
921 Value ex = calc->exp (calc->mul (fVal, 2.0));
922 return calc->div (calc->sub (ex, 1.0), calc->add (ex, 1.0));
923}
924
925// Function: normdist
926Value func_normdist (valVector args, ValueCalc *calc, FuncExtra *) {
927 //returns the normal cumulative distribution
928 Value x = args[0];
929 Value mue = args[1];
930 Value sigma = args[2];
931 Value k = args[3];
932
933 if (!calc->greater (sigma, 0.0))
934 return Value::errorVALUE();
935
936 // (x - mue) / sigma
937 Value Y = calc->div (calc->sub (x, mue), sigma);
938 if (calc->isZero (k)) // density
939 return calc->div (calc->phi (Y), sigma);
940 else // distribution
941 return calc->add (calc->gauss (Y), 0.5);
942}
943
944// Function: lognormdist
945Value func_lognormdist (valVector args, ValueCalc *calc, FuncExtra *) {
946 //returns the cumulative lognormal distribution
947 Value x = args[0];
948 Value mue = args[1];
949 Value sigma = args[2];
950
951 if (!calc->greater (sigma, 0.0) || (!calc->greater (x, 0.0)))
952 return Value::errorVALUE();
953
954 // (ln(x) - mue) / sigma
955 Value Y = calc->div (calc->sub (calc->ln (x), mue), sigma);
956 return calc->add (calc->gauss (Y), 0.5);
957}
958
959// Function: normsdist
960Value func_stdnormdist (valVector args, ValueCalc *calc, FuncExtra *)
961{
962 //returns the cumulative lognormal distribution, mue=0, sigma=1
963 return calc->add (calc->gauss (args[0]), 0.5);
964}
965
966// Function: expondist
967Value func_expondist (valVector args, ValueCalc *calc, FuncExtra *) {
968 //returns the exponential distribution
969 Value x = args[0];
970 Value lambda = args[1];
971 Value kum = args[2];
972
973 Value result = 0.0;
974
975 if (!calc->greater (lambda, 0.0))
976 return Value::errorVALUE();
977
978 // ex = exp (-lambda * x)
979 Value ex = calc->exp (calc->mul (calc->mul (lambda, -1), x));
980 if (calc->isZero (kum)) { //density
981 if (!calc->lower (x, 0.0))
982 // lambda * ex
983 result = calc->mul (lambda, ex);
984 }
985 else { //distribution
986 if (calc->greater (x, 0.0))
987 // 1.0 - ex
988 result = calc->sub (1.0, ex);
989 }
990 return result;
991}
992
993// Function: weibull
994Value func_weibull (valVector args, ValueCalc *calc, FuncExtra *) {
995 //returns the Weibull distribution
996
997 Value x = args[0];
998 Value alpha = args[1];
999 Value beta = args[2];
1000 Value kum = args[3];
1001
1002 Value result;
1003
1004 if ((!calc->greater (alpha, 0.0)) || (!calc->greater (beta, 0.0)) ||
1005 calc->lower (x, 0.0))
1006 return Value::errorVALUE();
1007
1008 // ex = exp (-pow (x / beta, alpha))
1009 Value ex;
1010 ex = calc->exp (calc->mul (calc->pow (calc->div (x, beta), alpha), -1));
1011 if (calc->isZero (kum)) // density
1012 {
1013 // result = alpha / pow(beta,alpha) * pow(x,alpha-1.0) * ex
1014 result = calc->div (alpha, calc->pow (beta, alpha));
1015 result = calc->mul (result, calc->mul (calc->pow (x,
1016 calc->sub (alpha, 1)), ex));
1017 }
1018 else // distribution
1019 result = calc->sub (1.0, ex);
1020
1021 return result;
1022}
1023
1024// Function: normsinv
1025Value func_normsinv (valVector args, ValueCalc *calc, FuncExtra *) {
1026 //returns the inverse of the standard normal cumulative distribution
1027
1028 Value x = args[0];
1029 if (!(calc->greater (x, 0.0) && calc->lower (x, 1.0)))
1030 return Value::errorVALUE();
1031
1032 return calc->gaussinv (x);
1033}
1034
1035// Function: norminv
1036Value func_norminv (valVector args, ValueCalc *calc, FuncExtra *) {
1037 //returns the inverse of the normal cumulative distribution
1038 Value x = args[0];
1039 Value mue = args[1];
1040 Value sigma = args[2];
1041
1042 if (!calc->greater (sigma, 0.0))
1043 return Value::errorVALUE();
1044 if (!(calc->greater (x, 0.0) && calc->lower (x, 1.0)))
1045 return Value::errorVALUE();
1046
1047 // gaussinv (x)*sigma + mue
1048 return calc->add (calc->mul (calc->gaussinv (x), sigma), mue);
1049}
1050
1051// Function: gammaln
1052Value func_gammaln (valVector args, ValueCalc *calc, FuncExtra *) {
1053 //returns the natural logarithm of the gamma function
1054
1055 if (calc->greater (args[0], 0.0))
1056 return calc->GetLogGamma (args[0]);
1057 return Value::errorVALUE();
1058}
1059
1060// Function: poisson
1061Value func_poisson (valVector args, ValueCalc *calc, FuncExtra *) {
1062 //returns the Poisson distribution
1063
1064 Value x = args[0];
1065 Value lambda = args[1];
1066 Value kum = args[2];
1067
1068 // lambda < 0.0 || x < 0.0
1069 if (calc->lower (lambda, 0.0) || calc->lower (x, 0.0))
1070 return Value::errorVALUE();
1071
1072 Value result;
1073
1074 // ex = exp (-lambda)
1075 Value ex = calc->exp (calc->mul (lambda, -1));
1076
1077 if (calc->isZero (kum)) { // density
1078 if (calc->isZero (lambda))
1079 result = 0;
1080 else
1081 // ex * pow (lambda, x) / fact (x)
1082 result = calc->div (calc->mul (ex, calc->pow (lambda, x)), calc->fact (x));
1083 }
1084 else { // distribution
1085 if (calc->isZero (lambda))
1086 result = 1;
1087 else
1088 {
1089 result = 1.0;
1090 Value fFak = 1.0;
1091 unsigned long nEnd = calc->conv()->asInteger (x).asInteger();
1092 for (unsigned long i = 1; i <= nEnd; i++)
1093 {
1094 // fFak *= i
1095 fFak = calc->mul (fFak, i);
1096 // result += pow (lambda, i) / fFak
1097 result = calc->add (result, calc->div (calc->pow (lambda, i), fFak));
1098 }
1099 result = calc->mul (result, ex);
1100 }
1101 }
1102
1103 return result;
1104}
1105
1106// Function: confidence
1107Value func_confidence (valVector args, ValueCalc *calc, FuncExtra *) {
1108 //returns the confidence interval for a population mean
1109 Value alpha = args[0];
1110 Value sigma = args[1];
1111 Value n = args[2];
1112
1113 // sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1
1114 if ((!calc->greater (sigma, 0.0)) || (!calc->greater (alpha, 0.0)) ||
1115 (!calc->lower (alpha, 1.0)) || calc->lower (n, 1))
1116 return Value::errorVALUE();
1117
1118 // g = gaussinv (1.0 - alpha / 2.0)
1119 Value g = calc->gaussinv (calc->sub (1.0, calc->div (alpha, 2.0)));
1120 // g * sigma / sqrt (n)
1121 return calc->div (calc->mul (g, sigma), calc->sqrt (n));
1122}
1123
1124// Function: tdist
1125Value func_tdist (valVector args, ValueCalc *calc, FuncExtra *) {
1126 //returns the t-distribution
1127
1128 Value T = args[0];
1129 Value fDF = args[1];
1130 int flag = calc->conv()->asInteger (args[2]).asInteger();
1131
1132 if (calc->lower (fDF, 1) || calc->lower (T, 0.0) || (flag != 1 && flag != 2))
1133 return Value::errorVALUE();
1134
1135 // arg = fDF / (fDF + T * T)
1136 Value arg = calc->div (fDF, calc->add (fDF, calc->sqr (T)));
1137
1138 Value R;
1139 R = calc->mul (calc->GetBeta (arg, calc->div (fDF, 2.0), 0.5), 0.5);
1140
1141 if (flag == 1)
1142 return R;
1143 return calc->mul (R, 2); // flag is 2 here
1144}
1145
1146// Function: fdist
1147Value func_fdist (valVector args, ValueCalc *calc, FuncExtra *) {
1148 //returns the f-distribution
1149
1150 Value x = args[0];
1151 Value fF1 = args[1];
1152 Value fF2 = args[2];
1153
1154 // x < 0.0 || fF1 < 1 || fF2 < 1 || fF1 >= 1.0E10 || fF2 >= 1.0E10
1155 if (calc->lower (x, 0.0) || calc->lower (fF1, 1) || calc->lower (fF2, 1) ||
1156 (!calc->lower (fF1, 1.0E10)) || (!calc->lower (fF2, 1.0E10)))
1157 return Value::errorVALUE();
1158
1159 // arg = fF2 / (fF2 + fF1 * x)
1160 Value arg = calc->div (fF2, calc->add (fF2, calc->mul (fF1, x)));
1161 // alpha = fF2/2.0
1162 Value alpha = calc->div (fF2, 2.0);
1163 // beta = fF1/2.0
1164 Value beta = calc->div (fF1, 2.0);
1165 return calc->GetBeta (arg, alpha, beta);
1166}
1167
1168// Function: chidist
1169Value func_chidist (valVector args, ValueCalc *calc, FuncExtra *) {
1170 //returns the chi-distribution
1171
1172 Value fChi = args[0];
1173 Value fDF = args[1];
1174
1175 // fDF < 1 || fDF >= 1.0E5 || fChi < 0.0
1176 if (calc->lower (fDF, 1) || (!calc->lower (fDF, 1.0E5)) ||
1177 calc->lower (fChi, 0.0))
1178 return Value::errorVALUE();
1179
1180 // 1.0 - GetGammaDist (fChi / 2.0, fDF / 2.0, 1.0)
1181 return calc->sub (1.0, calc->GetGammaDist (calc->div (fChi, 2.0),
1182 calc->div (fDF, 2.0), 1.0));
1183}
1184
1185
1186// two-array-walk functions used in the two-sum functions
1187
1188void tawSumproduct (ValueCalc *c, Value &res, Value v1,
1189 Value v2) {
1190 // res += v1*v2
1191 res = c->add (res, c->mul (v1, v2));
1192}
1193
1194void tawSumx2py2 (ValueCalc *c, Value &res, Value v1,
1195 Value v2) {
1196 // res += sqr(v1)+sqr(v2)
1197 res = c->add (res, c->add (c->sqr (v1), c->sqr (v2)));
1198}
1199
1200void tawSumx2my2 (ValueCalc *c, Value &res, Value v1,
1201 Value v2) {
1202 // res += sqr(v1)-sqr(v2)
1203 res = c->add (res, c->sub (c->sqr (v1), c->sqr (v2)));
1204}
1205
1206void tawSumxmy2 (ValueCalc *c, Value &res, Value v1,
1207 Value v2) {
1208 // res += sqr(v1-v2)
1209 res = c->add (res, c->sqr (c->sub (v1, v2)));
1210
1211}
1212
1213// Function: sumproduct
1214Value func_sumproduct (valVector args, ValueCalc *calc, FuncExtra *)
1215{
1216 Value result;
1217 calc->twoArrayWalk (args[0], args[1], result, tawSumproduct);
1218 return result;
1219}
1220
1221// Function: sumx2py2
1222Value func_sumx2py2 (valVector args, ValueCalc *calc, FuncExtra *)
1223{
1224 Value result;
1225 calc->twoArrayWalk (args[0], args[1], result, tawSumx2py2);
1226 return result;
1227}
1228
1229// Function: sumx2my2
1230Value func_sumx2my2 (valVector args, ValueCalc *calc, FuncExtra *)
1231{
1232 Value result;
1233 calc->twoArrayWalk (args[0], args[1], result, tawSumx2my2);
1234 return result;
1235}
1236
1237// Function: sum2xmy
1238Value func_sumxmy2 (valVector args, ValueCalc *calc, FuncExtra *)
1239{
1240 Value result;
1241 calc->twoArrayWalk (args[0], args[1], result, tawSumxmy2);
1242 return result;
1243}
The ValueCalc class is used to perform all sorts of calculations.
Definition valuecalc.h:69
Value phi(Value x)
some statistical stuff TODO: we may want to move these over to a separate class or something,...
bool greater(const Value &a, const Value &b)
numerical comparison
bool isZero(const Value &a)
comparison and related
Value fact(const Value &which)
some computational functions
Value combin(int n, int k)
combinations
bool equal(const Value &a, const Value &b)
numerical comparison
void arrayWalk(const Value &range, Value &res, arrayWalkFunc func, Value param)
array/range walking
bool lower(const Value &a, const Value &b)
numerical comparison
Value add(const Value &a, const Value &b)
basic arithmetic operations
Provides a wrapper for cell value.
unsigned columns() const
If this value is an array, return the number of columns.
Value element(unsigned column, unsigned row) const
Return an element in the array value.
static const Value & errorDIV0()
Returns constant reference to #DIV/0! error.
unsigned rows() const
If this value is an array, return the number of rows.
bool isArray() const
Returns true if the type of this value is array.
double asFloat() const
Returns the floating-point value of this value.
long asInteger() const
Returns the integer value of this value.
static const Value & errorVALUE()
Returns constant reference to #VALUE! error.
The KSpread namespace.
Definition commands.h:39