kspread

kspread_functions_math.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 math functions
23
24#include <kdebug.h>
25#include <tdelocale.h>
26
27#include "functions.h"
28#include "valuecalc.h"
29#include "valueconverter.h"
30
31// these two are needed for SUBTOTAL:
32#include "kspread_cell.h"
33#include "kspread_sheet.h"
34
35// needed for RANDBINOM and so
36#include <math.h>
37
38using namespace KSpread;
39
40// RANDBINOM and RANDNEGBINOM won't support arbitrary precision
41
42// prototypes
43Value func_abs (valVector args, ValueCalc *calc, FuncExtra *);
44Value func_ceil (valVector args, ValueCalc *calc, FuncExtra *);
45Value func_ceiling (valVector args, ValueCalc *calc, FuncExtra *);
46Value func_count (valVector args, ValueCalc *calc, FuncExtra *);
47Value func_counta (valVector args, ValueCalc *calc, FuncExtra *);
48Value func_countblank (valVector args, ValueCalc *calc, FuncExtra *);
49Value func_countif (valVector args, ValueCalc *calc, FuncExtra *);
50Value func_cur (valVector args, ValueCalc *calc, FuncExtra *);
51Value func_div (valVector args, ValueCalc *calc, FuncExtra *);
52Value func_eps (valVector args, ValueCalc *calc, FuncExtra *);
53Value func_even (valVector args, ValueCalc *calc, FuncExtra *);
54Value func_exp (valVector args, ValueCalc *calc, FuncExtra *);
55Value func_fact (valVector args, ValueCalc *calc, FuncExtra *);
56Value func_factdouble (valVector args, ValueCalc *calc, FuncExtra *);
57Value func_fib (valVector args, ValueCalc *calc, FuncExtra *);
58Value func_floor (valVector args, ValueCalc *calc, FuncExtra *);
59Value func_gcd (valVector args, ValueCalc *calc, FuncExtra *);
60Value func_int (valVector args, ValueCalc *calc, FuncExtra *);
61Value func_inv (valVector args, ValueCalc *calc, FuncExtra *);
62Value func_kproduct (valVector args, ValueCalc *calc, FuncExtra *);
63Value func_lcm (valVector args, ValueCalc *calc, FuncExtra *);
64Value func_ln (valVector args, ValueCalc *calc, FuncExtra *);
65Value func_log2 (valVector args, ValueCalc *calc, FuncExtra *);
66Value func_log10 (valVector args, ValueCalc *calc, FuncExtra *);
67Value func_logn (valVector args, ValueCalc *calc, FuncExtra *);
68Value func_max (valVector args, ValueCalc *calc, FuncExtra *);
69Value func_maxa (valVector args, ValueCalc *calc, FuncExtra *);
70Value func_mdeterm (valVector args, ValueCalc *calc, FuncExtra *);
71Value func_min (valVector args, ValueCalc *calc, FuncExtra *);
72Value func_mina (valVector args, ValueCalc *calc, FuncExtra *);
73Value func_mmult (valVector args, ValueCalc *calc, FuncExtra *);
74Value func_mod (valVector args, ValueCalc *calc, FuncExtra *);
75Value func_mround (valVector args, ValueCalc *calc, FuncExtra *);
76Value func_mult (valVector args, ValueCalc *calc, FuncExtra *);
77Value func_multinomial (valVector args, ValueCalc *calc, FuncExtra *);
78Value func_odd (valVector args, ValueCalc *calc, FuncExtra *);
79Value func_pow (valVector args, ValueCalc *calc, FuncExtra *);
80Value func_quotient (valVector args, ValueCalc *calc, FuncExtra *);
81Value func_product (valVector args, ValueCalc *calc, FuncExtra *);
82Value func_rand (valVector args, ValueCalc *calc, FuncExtra *);
83Value func_randbetween (valVector args, ValueCalc *calc, FuncExtra *);
84Value func_randbernoulli (valVector args, ValueCalc *calc, FuncExtra *);
85Value func_randbinom (valVector args, ValueCalc *calc, FuncExtra *);
86Value func_randexp (valVector args, ValueCalc *calc, FuncExtra *);
87Value func_randnegbinom (valVector args, ValueCalc *calc, FuncExtra *);
88Value func_randnorm (valVector args, ValueCalc *calc, FuncExtra *);
89Value func_randpoisson (valVector args, ValueCalc *calc, FuncExtra *);
90Value func_rootn (valVector args, ValueCalc *calc, FuncExtra *);
91Value func_round (valVector args, ValueCalc *calc, FuncExtra *);
92Value func_rounddown (valVector args, ValueCalc *calc, FuncExtra *);
93Value func_roundup (valVector args, ValueCalc *calc, FuncExtra *);
94Value func_sign (valVector args, ValueCalc *calc, FuncExtra *);
95Value func_sqrt (valVector args, ValueCalc *calc, FuncExtra *);
96Value func_sqrtpi (valVector args, ValueCalc *calc, FuncExtra *);
97Value func_subtotal (valVector args, ValueCalc *calc, FuncExtra *);
98Value func_sum (valVector args, ValueCalc *calc, FuncExtra *);
99Value func_suma (valVector args, ValueCalc *calc, FuncExtra *);
100Value func_sumif (valVector args, ValueCalc *calc, FuncExtra *);
101Value func_sumsq (valVector args, ValueCalc *calc, FuncExtra *);
102Value func_trunc (valVector args, ValueCalc *calc, FuncExtra *);
103
104
105// Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *);
106
107// registers all math functions
108void RegisterMathFunctions()
109{
110 FunctionRepository* repo = FunctionRepository::self();
111 Function *f;
112
113/*
114 f = new Function ("MULTIPLEOPERATIONS", func_multipleOP);
115 repo->add (f);
116*/
117
118 // functions that don't take array parameters
119 f = new Function ("ABS", func_abs);
120 repo->add (f);
121 f = new Function ("CEIL", func_ceil);
122 repo->add (f);
123 f = new Function ("CEILING", func_ceiling);
124 f->setParamCount (1, 2);
125 repo->add (f);
126 f = new Function ("CUR", func_cur);
127 repo->add (f);
128 f = new Function ("EPS", func_eps);
129 f->setParamCount (0);
130 repo->add (f);
131 f = new Function ("EVEN", func_even);
132 repo->add (f);
133 f = new Function ("EXP", func_exp);
134 repo->add (f);
135 f = new Function ("FACT", func_fact);
136 repo->add (f);
137 f = new Function ("FACTDOUBLE", func_factdouble);
138 repo->add (f);
139 f = new Function ("FIB", func_fib); // KSpread-specific, like Quattro-Pro's FIB
140 repo->add (f);
141 f = new Function ("FLOOR", func_floor);
142 repo->add (f);
143 f = new Function ("INT", func_int);
144 repo->add (f);
145 f = new Function ("INV", func_inv);
146 repo->add (f);
147 f = new Function ("LN", func_ln);
148 repo->add (f);
149 f = new Function ("LOG", func_log10);
150 repo->add (f);
151 f = new Function ("LOG2", func_log2);
152 repo->add (f);
153 f = new Function ("LOG10", func_log10); // same as LOG
154 repo->add (f);
155 f = new Function ("LOGN", func_logn);
156 f->setParamCount (2);
157 repo->add (f);
158 f = new Function ("MOD", func_mod);
159 f->setParamCount (2);
160 repo->add (f);
161 f = new Function ("MROUND", func_mround);
162 f->setParamCount (2);
163 repo->add (f);
164 f = new Function ("MULTINOMIAL", func_multinomial);
165 f->setParamCount (1, -1);
166 repo->add (f);
167 f = new Function ("ODD", func_odd);
168 repo->add (f);
169 f = new Function ("POW", func_pow);
170 f->setParamCount (2);
171 repo->add (f);
172 f = new Function ("POWER", func_pow);
173 f->setParamCount (2);
174 repo->add (f);
175 f = new Function ("QUOTIENT", func_quotient);
176 f->setParamCount (2);
177 repo->add (f);
178 f = new Function ("RAND", func_rand);
179 f->setParamCount (0);
180 repo->add (f);
181 f = new Function ("RANDBERNOULLI", func_randbernoulli);
182 repo->add (f);
183 f = new Function ("RANDBETWEEN", func_randbetween);
184 f->setParamCount (2);
185 repo->add (f);
186 f = new Function ("RANDBINOM", func_randbinom);
187 f->setParamCount (2);
188 repo->add (f);
189 f = new Function ("RANDEXP", func_randexp);
190 repo->add (f);
191 f = new Function ("RANDNEGBINOM", func_randnegbinom);
192 f->setParamCount (2);
193 repo->add (f);
194 f = new Function ("RANDNORM", func_randnorm);
195 f->setParamCount (2);
196 repo->add (f);
197 f = new Function ("RANDPOISSON", func_randpoisson);
198 repo->add (f);
199 f = new Function ("ROOTN", func_rootn);
200 f->setParamCount (2);
201 repo->add (f);
202 f = new Function ("ROUND", func_round);
203 f->setParamCount (1, 2);
204 repo->add (f);
205 f = new Function ("ROUNDDOWN", func_rounddown);
206 f->setParamCount (1, 2);
207 repo->add (f);
208 f = new Function ("ROUNDUP", func_roundup);
209 f->setParamCount (1, 2);
210 repo->add (f);
211 f = new Function ("SIGN", func_sign);
212 repo->add (f);
213 f = new Function ("SQRT", func_sqrt);
214 repo->add (f);
215 f = new Function ("SQRTPI", func_sqrtpi);
216 repo->add (f);
217 f = new Function ("TRUNC", func_trunc);
218 f->setParamCount (1, 2);
219 repo->add (f);
220
221 // functions that operate over arrays
222 f = new Function ("COUNT", func_count);
223 f->setParamCount (1, -1);
224 f->setAcceptArray ();
225 repo->add (f);
226 f = new Function ("COUNTA", func_counta);
227 f->setParamCount (1, -1);
228 f->setAcceptArray ();
229 repo->add (f);
230 f = new Function ("COUNTBLANK", func_countblank);
231 f->setParamCount (1, -1);
232 f->setAcceptArray ();
233 repo->add (f);
234 f = new Function ("COUNTIF", func_countif);
235 f->setParamCount (2);
236 f->setAcceptArray ();
237 repo->add (f);
238 f = new Function ("DIV", func_div);
239 f->setParamCount (1, -1);
240 f->setAcceptArray ();
241 repo->add (f);
242 f = new Function ("G_PRODUCT", func_kproduct); // Gnumeric compatibility
243 f->setParamCount (1, -1);
244 f->setAcceptArray ();
245 repo->add (f);
246 f = new Function ("GCD", func_gcd);
247 f->setParamCount (1, -1);
248 f->setAcceptArray ();
249 repo->add (f);
250 f = new Function ("KPRODUCT", func_kproduct);
251 f->setParamCount (1, -1);
252 f->setAcceptArray ();
253 repo->add (f);
254 f = new Function ("LCM", func_lcm);
255 f->setParamCount (1, -1);
256 f->setAcceptArray ();
257 repo->add (f);
258 f = new Function ("MAX", func_max);
259 f->setParamCount (1, -1);
260 f->setAcceptArray ();
261 repo->add (f);
262 f = new Function ("MAXA", func_maxa);
263 f->setParamCount (1, -1);
264 f->setAcceptArray ();
265 repo->add (f);
266 f = new Function ("MDETERM", func_mdeterm);
267 f->setParamCount (1);
268 f->setAcceptArray ();
269 repo->add (f);
270 f = new Function ("MIN", func_min);
271 f->setParamCount (1, -1);
272 f->setAcceptArray ();
273 repo->add (f);
274 f = new Function ("MINA", func_mina);
275 f->setParamCount (1, -1);
276 f->setAcceptArray ();
277 repo->add (f);
278 f = new Function ("MMULT", func_mmult);
279 f->setParamCount (2);
280 f->setAcceptArray ();
281 repo->add (f);
282 f = new Function ("MULTIPLY", func_product); // same as PRODUCT
283 f->setParamCount (1, -1);
284 f->setAcceptArray ();
285 repo->add (f);
286 f = new Function ("PRODUCT", func_product);
287 f->setParamCount (1, -1);
288 f->setAcceptArray ();
289 repo->add (f);
290 f = new Function ("SUM", func_sum);
291 f->setParamCount (1, -1);
292 f->setAcceptArray ();
293 repo->add (f);
294 f = new Function ("SUMA", func_suma);
295 f->setParamCount (1, -1);
296 f->setAcceptArray ();
297 repo->add (f);
298 f = new Function ("SUBTOTAL", func_subtotal);
299 f->setParamCount (2);
300 f->setAcceptArray ();
301 f->setNeedsExtra (true);
302 repo->add (f);
303 f = new Function ("SUMIF", func_sumif);
304 f->setParamCount (2, 3);
305 f->setAcceptArray ();
306 repo->add (f);
307 f = new Function ("SUMSQ", func_sumsq);
308 f->setParamCount (1, -1);
309 f->setAcceptArray ();
310 repo->add (f);
311}
312
313// Function: SQRT
314Value func_sqrt (valVector args, ValueCalc *calc, FuncExtra *)
315{
316 return calc->sqrt (args[0]);
317}
318
319// Function: SQRTPI
320Value func_sqrtpi (valVector args, ValueCalc *calc, FuncExtra *)
321{
322 // sqrt (val * PI)
323 return calc->sqrt (calc->mul (args[0], calc->pi()));
324}
325
326// Function: ROOTN
327Value func_rootn (valVector args, ValueCalc *calc, FuncExtra *)
328{
329 return calc->pow (args[0], calc->div (1, args[1]));
330}
331
332// Function: CUR
333Value func_cur (valVector args, ValueCalc *calc, FuncExtra *)
334{
335 return calc->pow (args[0], 1.0/3.0);
336}
337
338// Function: ABS
339Value func_abs (valVector args, ValueCalc *calc, FuncExtra *)
340{
341 return calc->abs (args[0]);
342}
343
344// Function: exp
345Value func_exp (valVector args, ValueCalc *calc, FuncExtra *)
346{
347 return calc->exp (args[0]);
348}
349
350// Function: ceil
351Value func_ceil (valVector args, ValueCalc *calc, FuncExtra *)
352{
353 return calc->roundUp (args[0], 0);
354}
355
356// Function: ceiling
357Value func_ceiling (valVector args, ValueCalc *calc, FuncExtra *)
358{
359 Value number = args[0];
360 Value res;
361 if (args.count() == 2)
362 res = args[1];
363 else
364 res = calc->gequal (number, 0.0) ? 1.0 : -1.0;
365
366 if (calc->isZero(res))
367 return Value::errorDIV0();
368
369 Value d = calc->div (number, res);
370 if (calc->greater (0, d))
371 return Value::errorVALUE();
372
373 Value rud = calc->roundDown (d);
374 if (calc->approxEqual (rud, d))
375 d = calc->mul (rud, res);
376 else
377 d = calc->mul (calc->roundUp (d), res);
378
379 return d;
380}
381
382// Function: floor
383Value func_floor (valVector args, ValueCalc *calc, FuncExtra *)
384{
385 return calc->roundDown (args[0], 0);
386}
387
388// Function: ln
389Value func_ln (valVector args, ValueCalc *calc, FuncExtra *)
390{
391 return calc->ln (args[0]);
392}
393
394// Function: LOGn
395Value func_logn (valVector args, ValueCalc *calc, FuncExtra *)
396{
397 return calc->log (args[0], args[1]);
398}
399
400// Function: LOG2
401Value func_log2 (valVector args, ValueCalc *calc, FuncExtra *)
402{
403 return calc->log (args[0], 2.0);
404}
405
406// Function: LOG10
407Value func_log10 (valVector args, ValueCalc *calc, FuncExtra *)
408{
409 return calc->log (args[0]);
410}
411
412// Function: sum
413Value func_sum (valVector args, ValueCalc *calc, FuncExtra *)
414{
415 return calc->sum (args, false);
416}
417
418// Function: suma
419Value func_suma (valVector args, ValueCalc *calc, FuncExtra *)
420{
421 return calc->sum (args, true);
422}
423
424Value func_sumif (valVector args, ValueCalc *calc, FuncExtra *)
425{
426 Value checkRange = args[0];
427 TQString condition = calc->conv()->asString (args[1]).asString();
428 Value sumRange = checkRange;
429 if (args.count() == 3)
430 sumRange = args[2];
431
432 Condition cond;
433 calc->getCond (cond, condition);
434
435 return calc->sumIf (sumRange, checkRange, cond);
436}
437
438// Function: product
439Value func_product (valVector args, ValueCalc *calc, FuncExtra *)
440{
441 return calc->product (args, 0.0);
442}
443
444// Function: kproduct
445Value func_kproduct (valVector args, ValueCalc *calc, FuncExtra *)
446{
447 return calc->product (args, 1.0);
448}
449
450// Function: DIV
451Value func_div (valVector args, ValueCalc *calc, FuncExtra *)
452{
453 Value val = args[0];
454 for (unsigned int i = 1; i < args.count(); ++i)
455 {
456 val = calc->div (val, args[i]);
457 if (val.isError())
458 return val;
459 }
460 return val;
461}
462
463// Function: SUMSQ
464Value func_sumsq (valVector args, ValueCalc *calc, FuncExtra *)
465{
466 Value res;
467 calc->arrayWalk (args, res, calc->awFunc ("sumsq"), 0);
468 return res;
469}
470
471// Function: MAX
472Value func_max (valVector args, ValueCalc *calc, FuncExtra *)
473{
474 Value m = calc->max (args, false);
475 return m.isEmpty() ? Value(0.0) : m;
476}
477
478// Function: MAXA
479Value func_maxa (valVector args, ValueCalc *calc, FuncExtra *)
480{
481 Value m = calc->max (args);
482 return m.isEmpty() ? Value(0.0) : m;
483}
484
485// Function: MIN
486Value func_min (valVector args, ValueCalc *calc, FuncExtra *)
487{
488 Value m = calc->min (args, false);
489 return m.isEmpty() ? Value(0.0) : m;
490}
491
492// Function: MINA
493Value func_mina (valVector args, ValueCalc *calc, FuncExtra *)
494{
495 Value m = calc->min (args);
496 return m.isEmpty() ? Value(0.0) : m;
497}
498
499// Function: INT
500Value func_int (valVector args, ValueCalc *calc, FuncExtra *)
501{
502 return calc->conv()->asInteger (args[0]);
503}
504
505// Function: QUOTIENT
506Value func_quotient (valVector args, ValueCalc *calc, FuncExtra *)
507{
508 if (calc->isZero (args[1]))
509 return Value::errorDIV0();
510 return calc->conv()->asInteger (calc->div (args[0], args[1]));
511}
512
513
514// Function: eps
515Value func_eps (valVector, ValueCalc *calc, FuncExtra *)
516{
517 return calc->eps ();
518}
519
520Value func_randexp (valVector args, ValueCalc *calc, FuncExtra *)
521{
522 // -1 * d * log (random)
523 return calc->mul (calc->mul (args[0], -1), calc->random());
524}
525
526Value func_randbinom (valVector args, ValueCalc *calc, FuncExtra *)
527{
528 // this function will not support arbitrary precision
529
530 double d = calc->conv()->asFloat (args[0]).asFloat();
531 int tr = calc->conv()->asInteger (args[1]).asInteger();
532
533 if ( d < 0 || d > 1 )
534 return Value::errorVALUE();
535
536 if ( tr < 0 )
537 return Value::errorVALUE();
538
539 // taken from gnumeric
540 double x = pow(1 - d, tr);
541 double r = (double) rand() / ( RAND_MAX + 1.0 );
542 double t = x;
543 int i = 0;
544
545 while (r > t)
546 {
547 x *= (((tr - i) * d) / ((1 + i) * (1 - d)));
548 i++;
549 t += x;
550 }
551
552 return Value (i);
553}
554
555Value func_randnegbinom (valVector args, ValueCalc *calc, FuncExtra *)
556{
557 // this function will not support arbitrary precision
558
559 double d = calc->conv()->asFloat (args[0]).asFloat();
560 int f = calc->conv()->asInteger (args[1]).asInteger();
561
562 if ( d < 0 || d > 1 )
563 return Value::errorVALUE();
564
565 if ( f < 0 )
566 return Value::errorVALUE();
567
568
569 // taken from Gnumeric
570 double x = pow(d, f);
571 double r = (double) rand() / ( RAND_MAX + 1.0 );
572 double t = x;
573 int i = 0;
574
575 while (r > t)
576 {
577 x *= ( ( ( f + i ) * ( 1 - d ) ) / (1 + i) ) ;
578 i++;
579 t += x;
580 }
581
582 return Value (i);
583}
584
585Value func_randbernoulli (valVector args, ValueCalc *calc, FuncExtra *)
586{
587 Value rnd = calc->random ();
588 return Value (calc->greater (rnd, args[0]) ? 1.0 : 0.0);
589}
590
591Value func_randnorm (valVector args, ValueCalc *calc, FuncExtra *)
592{
593 Value mu = args[0];
594 Value sigma = args[1];
595
596 //using polar form of the Box-Muller transformation
597 //refer to http://www.taygeta.com/random/gaussian.html for more info
598
599 Value x1, x2, w;
600 do {
601 // x1,x2 = 2 * random() - 1
602 x1 = calc->random (2.0);
603 x2 = calc->random (2.0);
604 x1 = calc->sub (x1, 1);
605 x1 = calc->sub (x2, 1);
606 w = calc->add (calc->sqr(x1), calc->sqr (x2));
607 } while (calc->gequal (w, 1.0)); // w >= 1.0
608
609 //sqrt ((-2.0 * log (w)) / w) :
610 w = calc->sqrt (calc->div (calc->mul (-2.0, calc->ln (w)), w));
611 Value res = calc->mul (x1, w);
612
613 res = calc->add (calc->mul (res, sigma), mu); // res*sigma + mu
614 return res;
615}
616
617Value func_randpoisson (valVector args, ValueCalc *calc, FuncExtra *)
618{
619 if (calc->lower (args[0], 0))
620 return Value::errorVALUE();
621
622 // taken from Gnumeric...
623 Value x = calc->exp (calc->mul (-1, args[0])); // e^(-A)
624 Value r = calc->random ();
625 Value t = x;
626 int i = 0;
627
628 while (calc->greater (r, t)) { // r > t
629 x = calc->mul (x, calc->div (args[0], i + 1)); // x *= (A/(i+1))
630 t = calc->add (t, x); //t += x
631 i++;
632 }
633
634 return Value (i);
635}
636
637// Function: rand
638Value func_rand (valVector, ValueCalc *calc, FuncExtra *)
639{
640 return calc->random ();
641}
642
643// Function: RANDBETWEEN
644Value func_randbetween (valVector args, ValueCalc *calc, FuncExtra *)
645{
646 Value v1 = args[0];
647 Value v2 = args[1];
648 if (calc->greater (v2, v1)) {
649 v1 = args[1];
650 v2 = args[0];
651 }
652 return calc->add (v1, calc->random (calc->sub (v2, v1)));
653}
654
655// Function: POW
656Value func_pow (valVector args, ValueCalc *calc, FuncExtra *)
657{
658 return calc->pow (args[0], args[1]);
659}
660
661// Function: MOD
662Value func_mod (valVector args, ValueCalc *calc, FuncExtra *)
663{
664 return calc->mod (args[0], args[1]);
665}
666
667// Function: fact
668Value func_fact (valVector args, ValueCalc *calc, FuncExtra *)
669{
670 return calc->fact (args[0]);
671}
672
673// Function: FACTDOUBLE
674Value func_factdouble (valVector args, ValueCalc *calc, FuncExtra *)
675{
676 return calc->factDouble (args[0]);
677}
678
679// Function: MULTINOMIAL
680Value func_multinomial (valVector args, ValueCalc *calc, FuncExtra *)
681{
682 // (a+b+c)! / a!b!c! (any number of params possible)
683 Value num = 0, den = 1;
684 for (unsigned int i = 0; i < args.count(); ++i) {
685 num = calc->add (num, args[i]);
686 den = calc->mul (den, calc->fact (args[i]));
687 }
688 num = calc->fact (num);
689 return calc->div (num, den);
690}
691
692// Function: sign
693Value func_sign (valVector args, ValueCalc *calc, FuncExtra *)
694{
695 return Value (calc->sign (args[0]));
696}
697
698// Function: INV
699Value func_inv (valVector args, ValueCalc *calc, FuncExtra *)
700{
701 return calc->mul (args[0], -1);
702}
703
704Value func_mround (valVector args, ValueCalc *calc, FuncExtra *)
705{
706 Value d = args[0];
707 Value m = args[1];
708
709 // signs must be the same
710 if ((calc->greater (d, 0) && calc->lower (m, 0))
711 || (calc->lower (d, 0) && calc->greater (m, 0)))
712 return Value::errorVALUE();
713
714 int sign = 1;
715
716 if (calc->lower (d, 0))
717 {
718 sign = -1;
719 d = calc->mul (d, -1);
720 m = calc->mul (m, -1);
721 }
722
723 // from gnumeric:
724 Value mod = calc->mod (d, m);
725 Value div = calc->sub (d, mod);
726
727 Value result = div;
728 if (calc->greater (mod, calc->div (m, 2))) // mod > m/2
729 result = calc->add (result, m); // result += m
730 result = calc->mul (result, sign); // add the sign
731
732 return result;
733}
734
735// Function: ROUNDDOWN
736Value func_rounddown (valVector args, ValueCalc *calc, FuncExtra *)
737{
738 if (args.count() == 2)
739 return calc->roundDown (args[0], args[1]);
740 return calc->roundDown (args[0], 0);
741}
742
743// Function: ROUNDUP
744Value func_roundup (valVector args, ValueCalc *calc, FuncExtra *)
745{
746 if (args.count() == 2)
747 return calc->roundUp (args[0], args[1]);
748 return calc->roundUp (args[0], 0);
749}
750
751// Function: ROUND
752Value func_round (valVector args, ValueCalc *calc, FuncExtra *)
753{
754 if (args.count() == 2)
755 return calc->round (args[0], args[1]);
756 return calc->round (args[0], 0);
757}
758
759// Function: EVEN
760Value func_even (valVector args, ValueCalc *calc, FuncExtra *)
761{
762 const Value value = calc->roundUp (args[0], 0);
763 return calc->isZero( calc->mod(value, 2) ) ? value : calc->add(value, 1);
764}
765
766// Function: ODD
767Value func_odd (valVector args, ValueCalc *calc, FuncExtra *)
768{
769 const Value value = calc->roundUp (args[0], 0);
770 return calc->isZero( calc->mod(value, 2) ) ? calc->add(value, 1) : value;
771}
772
773Value func_trunc (valVector args, ValueCalc *calc, FuncExtra *)
774{
775 if (args.count() == 1)
776 return calc->roundDown (args[0]);
777 return calc->roundDown (args[0], args[1]);
778}
779
780// Function: COUNT
781Value func_count (valVector args, ValueCalc *calc, FuncExtra *)
782{
783 return calc->count (args, false);
784}
785
786// Function: COUNTA
787Value func_counta (valVector args, ValueCalc *calc, FuncExtra *)
788{
789 return calc->count (args);
790}
791
792// Function: COUNTBLANK
793Value func_countblank (valVector args, ValueCalc *, FuncExtra *)
794{
795 int cnt = 0;
796 for (unsigned int i = 0; i < args.count(); ++i)
797 if (args[i].isArray()) {
798 int rows = args[i].rows();
799 int cols = args[i].columns();
800 for (int r = 0; r < rows; ++r)
801 for (int c = 0; c < cols; ++c)
802 if (args[i].element (c, r).isEmpty())
803 cnt++;
804 } else
805 if (args[i].isEmpty())
806 cnt++;
807 return Value (cnt);
808}
809
810// Function: COUNTIF
811Value func_countif (valVector args, ValueCalc *calc, FuncExtra *)
812{
813 Value range = args[0];
814 TQString condition = calc->conv()->asString (args[1]).asString();
815
816 Condition cond;
817 calc->getCond (cond, condition);
818
819 return calc->countIf (range, cond);
820}
821
822// Function: FIB
823Value func_fib (valVector args, ValueCalc *calc, FuncExtra *)
824{
825/*
826Lucas' formula for the nth Fibonacci number F(n) is given by
827
828 ((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n
829 F(n) = ------------------------------------- .
830 sqrt(5)
831
832*/
833 Value n = args[0];
834 Value s = calc->sqrt (5.0);
835 // u1 = ((1+sqrt(5))/2)^n
836 Value u1 = calc->pow (calc->div (calc->add (1, s), 2), n);
837 // u2 = ((1-sqrt(5))/2)^n
838 Value u2 = calc->pow (calc->div (calc->sub (1, s), 2), n);
839
840 Value result = calc->div (calc->sub (u1, u2), s);
841 return result;
842}
843
844static Value func_gcd_helper(const Value &val, ValueCalc *calc)
845{
846 Value res = 0;
847 if (!val.isArray ())
848 return val;
849 for (unsigned int row = 0; row < val.rows(); ++row)
850 for (unsigned int col = 0; col < val.columns(); ++col)
851 {
852 Value v = val.element (col, row);
853 if (v.isArray ())
854 v = func_gcd_helper (v, calc);
855 res = calc->gcd (res, v);
856 }
857 return res;
858}
859
860// Function: GCD
861Value func_gcd (valVector args, ValueCalc *calc, FuncExtra *)
862{
863 Value result = 0;
864 for (unsigned int i = 0; i < args.count(); ++i)
865 if (args[i].isArray())
866 result = calc->gcd (result, func_gcd_helper (args[i], calc));
867 else
868 result = calc->gcd (result, args[i]);
869 return result;
870}
871
872static Value func_lcm_helper(const Value &val, ValueCalc *calc)
873{
874 Value res = 0;
875 if (!val.isArray ())
876 return val;
877 for (unsigned int row = 0; row < val.rows(); ++row)
878 for (unsigned int col = 0; col < val.columns(); ++col)
879 {
880 Value v = val.element (col, row);
881 if (v.isArray ())
882 v = func_lcm_helper (v, calc);
883 res = calc->lcm (res, v);
884 }
885 return res;
886}
887
888// Function: lcm
889Value func_lcm (valVector args, ValueCalc *calc, FuncExtra *)
890{
891 Value result = 0;
892 for (unsigned int i = 0; i < args.count(); ++i)
893 if (args[i].isArray())
894 result = calc->lcm (result, func_lcm_helper (args[i], calc));
895 else
896 result = calc->lcm (result, args[i]);
897 return result;
898}
899
900Value determinant (ValueCalc *calc, Value matrix)
901{
902 // this is a --- SLOOOW --- recursive function
903 // using this for something bigger than 10x10 or so = suicide :P
904 // but I'm too lazy to adjust gnumeric's code - remains as a TODO then
905 // as a note, gnumeric uses LUP decomposition to compute this
906
907 // take first row, generate smaller matrices, recursion, multiply
908 Value res = 0.0;
909 int n = matrix.columns();
910 if (n == 1) return matrix.element (0, 0);
911 if (n == 2) return calc->sub (
912 calc->mul (matrix.element (1,1), matrix.element (0,0)),
913 calc->mul (matrix.element (1,0), matrix.element (0,1)));
914
915 // n >= 3
916 for (int i = 0; i < n; ++i) {
917 Value smaller (n-1, n-1);
918 int col = 0;
919 for (int c = 0; c < n; ++c)
920 if (c != i) {
921 // copy column c to column col in new matrix
922 for (int r = 1; r < n; r++)
923 smaller.setElement (col, r-1, matrix.element (c, r));
924 col++;
925 }
926 Value minor = determinant (calc, smaller);
927 if (i % 2 == 1) minor = calc->mul (minor, -1);
928 res = calc->add (res, calc->mul (minor, matrix.element (i, 0)));
929 }
930 return res;
931}
932
933// Function: mdeterm
934Value func_mdeterm (valVector args, ValueCalc *calc, FuncExtra *)
935{
936 Value m = args[0];
937 unsigned r = m.rows ();
938 unsigned c = m.columns ();
939 if (r != c) // must be a square matrix
940 return Value::errorVALUE();
941
942 return determinant (calc, args[0]);
943}
944
945// Function: mmult
946Value func_mmult (valVector args, ValueCalc *calc, FuncExtra *)
947{
948 Value m1 = args[0];
949 Value m2 = args[1];
950 unsigned r1 = m1.rows ();
951 unsigned c1 = m1.columns ();
952 unsigned r2 = m2.rows ();
953 unsigned c2 = m2.columns ();
954 if (c1 != r2) // row/column counts must match
955 return Value::errorVALUE();
956
957 // create the resulting matrix
958 Value res (c2, r1);
959
960 // perform the multiplication - O(n^3) algorithm
961 for (uint row = 0; row < r1; ++row)
962 for (uint col = 0; col < c2; ++col) {
963 Value val = 0.0;
964 for (uint pos = 0; pos < c1; ++pos)
965 val = calc->add (val,
966 calc->mul (m1.element (pos, row), m2.element (col, pos)));
967 res.setElement (col, row, val);
968 }
969 return res;
970}
971
972// Function: SUBTOTAL
973// This function requires access to the Sheet and so on, because
974// it needs to check whether cells contain the SUBTOTAL formula or not ...
975// Cells containing a SUBTOTAL formula must be ignored.
976Value func_subtotal (valVector args, ValueCalc *calc, FuncExtra *e)
977{
978 int function = calc->conv()->asInteger (args[0]).asInteger();
979 Value range = args[1];
980 int r1 = -1, c1 = -1, r2 = -1, c2 = -1;
981 if (e) {
982 r1 = e->ranges[1].row1;
983 c1 = e->ranges[1].col1;
984 r2 = e->ranges[1].row2;
985 c2 = e->ranges[1].col2;
986 }
987
988 // if we have a range, run through it, and put an empty value to the place
989 // of all occurences of the SUBTOTAL function
990 Value empty;
991 if ((r1 > 0) && (c1 > 0) && (r2 > 0) && (c2 > 0)) {
992 for (int r = r1; r <= r2; ++r)
993 for (int c = c1; c <= c2; ++c) {
994 Cell *cell = e->sheet->cellAt (c, r);
995 if (cell->isDefault())
996 continue;
997 if (cell->isFormula() && cell->text().find ("SUBTOTAL", 0, false) != -1)
998 // cell contains the word SUBTOTAL - replace value with empty
999 range.setElement (c-c1, r-r1, empty);
1000 }
1001 }
1002
1003 // Good. Now we can execute the necessary function on the range.
1004 Value res;
1005 Function *f;
1006 valVector a;
1007 switch (function) {
1008 case 1: // Average
1009 res = calc->avg (range, false);
1010 break;
1011 case 2: // Count
1012 res = calc->count (range, false);
1013 break;
1014 case 3: // CountA
1015 res = calc->count (range);
1016 break;
1017 case 4: // MAX
1018 res = calc->max (range, false);
1019 break;
1020 case 5: // Min
1021 res = calc->min (range, false);
1022 break;
1023 case 6: // Product
1024 res = calc->product (range, 0.0, false);
1025 break;
1026 case 7: // StDev
1027 res = calc->stddev (range, false);
1028 break;
1029 case 8: // StDevP
1030 res = calc->stddevP (range, false);
1031 break;
1032 case 9: // Sum
1033 res = calc->sum (range, false);
1034 break;
1035 case 10: // Var
1036 f = FunctionRepository::self()->function ("VAR");
1037 if (!f) return Value::errorVALUE();
1038 a.reserve (1);
1039 a[0] = range;
1040 res = f->exec (a, calc, 0);
1041 break;
1042 case 11: // VarP
1043 f = FunctionRepository::self()->function ("VARP");
1044 if (!f) return Value::errorVALUE();
1045 a.reserve (1);
1046 a[0] = range;
1047 res = f->exec (a, calc, 0);
1048 break;
1049 default:
1050 return Value::errorVALUE();
1051 }
1052 return res;
1053}
1054
1055/*
1056Commented out.
1057Absolutely no idea what this thing is supposed to do.
1058To anyone who would enable this code: it still uses koscript calls - you need
1059to convert it to the new style prior to uncommenting.
1060
1061// Function: MULTIPLEOPERATIONS
1062Value func_multipleOP (valVector args, ValueCalc *calc, FuncExtra *)
1063{
1064 if (gCell)
1065 {
1066 context.setValue( new KSValue( ((Interpreter *) context.interpreter() )->cell()->value().asFloat() ) );
1067 return true;
1068 }
1069
1070 gCell = ((Interpreter *) context.interpreter() )->cell();
1071
1072 TQValueList<KSValue::Ptr>& args = context.value()->listValue();
1073 TQValueList<KSValue::Ptr>& extra = context.extraData()->listValue();
1074
1075 if ( !KSUtil::checkArgumentsCount( context, 5, "MULTIPLEOPERATIONS", true ) )
1076 {
1077 gCell = 0;
1078 return false;
1079 }
1080
1081 // 0: cell must contain formula with double/int result
1082 // 0, 1, 2, 3, 4: must contain integer/double
1083 for (int i = 0; i < 5; ++i)
1084 {
1085 if ( !KSUtil::checkType( context, args[i], KSValue::DoubleType, true ) )
1086 {
1087 gCell = 0;
1088 return false;
1089 }
1090 }
1091
1092 // ((Interpreter *) context.interpreter() )->document()->emitBeginOperation();
1093
1094 double oldCol = args[1]->doubleValue();
1095 double oldRow = args[3]->doubleValue();
1096 kdDebug() << "Old values: Col: " << oldCol << ", Row: " << oldRow << endl;
1097
1098 Cell * cell;
1099 Sheet * sheet = ((Interpreter *) context.interpreter() )->sheet();
1100
1101 Point point( extra[1]->stringValue() );
1102 Point point2( extra[3]->stringValue() );
1103 Point point3( extra[0]->stringValue() );
1104
1105 if ( ( args[1]->doubleValue() != args[2]->doubleValue() )
1106 || ( args[3]->doubleValue() != args[4]->doubleValue() ) )
1107 {
1108 cell = sheet->cellAt( point.pos.x(), point.pos.y() );
1109 cell->setValue( args[2]->doubleValue() );
1110 kdDebug() << "Setting value " << args[2]->doubleValue() << " on cell " << point.pos.x()
1111 << ", " << point.pos.y() << endl;
1112
1113 cell = sheet->cellAt( point2.pos.x(), point.pos.y() );
1114 cell->setValue( args[4]->doubleValue() );
1115 kdDebug() << "Setting value " << args[4]->doubleValue() << " on cell " << point2.pos.x()
1116 << ", " << point2.pos.y() << endl;
1117 }
1118
1119 Cell * cell1 = sheet->cellAt( point3.pos.x(), point3.pos.y() );
1120 cell1->calc( false );
1121
1122 double d = cell1->value().asFloat();
1123 kdDebug() << "Cell: " << point3.pos.x() << "; " << point3.pos.y() << " with value "
1124 << d << endl;
1125
1126 kdDebug() << "Resetting old values" << endl;
1127
1128 cell = sheet->cellAt( point.pos.x(), point.pos.y() );
1129 cell->setValue( oldCol );
1130
1131 cell = sheet->cellAt( point2.pos.x(), point2.pos.y() );
1132 cell->setValue( oldRow );
1133
1134 cell1->calc( false );
1135
1136 // ((Interpreter *) context.interpreter() )->document()->emitEndOperation();
1137
1138 context.setValue( new KSValue( (double) d ) );
1139
1140 gCell = 0;
1141 return true;
1142}
1143
1144*/
For every cell in the spread sheet there is a Cell object.
The ValueCalc class is used to perform all sorts of calculations.
Definition valuecalc.h:69
Value gcd(const Value &a, const Value &b)
greatest common divisor
Value random(double range=1.0)
random number from <0.0, range)
Value sum(const Value &range, bool full=true)
basic range functions
bool gequal(const Value &a, const Value &b)
numerical comparison - greater or equal
bool approxEqual(const Value &a, const Value &b)
numerical comparison with a little epsilon tolerance
Value pi()
constants
Value factDouble(int which)
double factorial (every other number multiplied)
bool greater(const Value &a, const Value &b)
numerical comparison
bool isZero(const Value &a)
comparison and related
Value roundDown(const Value &a, const Value &digits)
rounding
Value fact(const Value &which)
some computational functions
void arrayWalk(const Value &range, Value &res, arrayWalkFunc func, Value param)
array/range walking
Value log(const Value &number, const Value &base)
logarithms and exponentials
void getCond(Condition &cond, Value val)
This method parses the condition in string text to the condition cond.
Value lcm(const Value &a, const Value &b)
lowest common multiplicator
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!
unsigned rows() const
If this value is an array, return the number of rows.
bool isEmpty() const
Returns true if empty.
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.
TQString asString() const
Returns the string value of this value.
void setElement(unsigned column, unsigned row, const Value &value)
Sets an element in the array value.
static const Value & errorVALUE()
Returns constant reference to VALUE!
bool isError() const
Returns true if this value holds error information.
The KSpread namespace.
Definition commands.h:39