summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-sheet/sheet.cpp
Unidiff
Diffstat (limited to 'noncore/apps/opie-sheet/sheet.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-sheet/sheet.cpp2069
1 files changed, 1881 insertions, 188 deletions
diff --git a/noncore/apps/opie-sheet/sheet.cpp b/noncore/apps/opie-sheet/sheet.cpp
index c2563c2..103b83b 100644
--- a/noncore/apps/opie-sheet/sheet.cpp
+++ b/noncore/apps/opie-sheet/sheet.cpp
@@ -14,12 +14,15 @@
14 14
15#include "sheet.h" 15#include "sheet.h"
16 16
17#include <qmainwindow.h> 17#include <qmainwindow.h>
18#include <qmessagebox.h> 18#include <qmessagebox.h>
19#include <math.h> 19#include <math.h>
20#include <stdlib.h>
21#include <stdio.h>
22#include <time.h>
20 23
21#define DEFAULT_COL_WIDTH 50 24#define DEFAULT_COL_WIDTH 50
22 25
23Sheet::Sheet(int numRows, int numCols, QWidget *parent) 26Sheet::Sheet(int numRows, int numCols, QWidget *parent)
24 :QTable(numRows, numCols, parent) 27 :QTable(numRows, numCols, parent)
25{ 28{
@@ -37,35 +40,38 @@ Sheet::Sheet(int numRows, int numCols, QWidget *parent)
37 40
38 sheetData.setAutoDelete(TRUE); 41 sheetData.setAutoDelete(TRUE);
39 clipboardData.setAutoDelete(TRUE); 42 clipboardData.setAutoDelete(TRUE);
40 for (int i=0; i<numCols; ++i) 43 for (int i=0; i<numCols; ++i)
41 horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH); 44 horizontalHeader()->setLabel(i, getHeaderString(i+1), DEFAULT_COL_WIDTH);
42 45
46
43 connect(this, SIGNAL(currentChanged(int, int)), this, SLOT(slotCellSelected(int, int))); 47 connect(this, SIGNAL(currentChanged(int, int)), this, SLOT(slotCellSelected(int, int)));
44 connect(this, SIGNAL(valueChanged(int, int)), this, SLOT(slotCellChanged(int, int))); 48 connect(this, SIGNAL(valueChanged(int, int)), this, SLOT(slotCellChanged(int, int)));
45} 49}
46 50
47Sheet::~Sheet() 51Sheet::~Sheet()
48{ 52{
49} 53}
50 54
51typeCellData *Sheet::findCellData(int row, int col) 55typeCellData *Sheet::findCellData(int row, int col)
52{ 56{
53 typeCellData *tempCellData; 57 typeCellData *tempCellData;
54 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next()) 58 for (tempCellData=sheetData.first(); tempCellData; tempCellData=sheetData.next())
55 if (tempCellData->row==row && tempCellData->col==col) 59 {
56 return tempCellData; 60 if (tempCellData->row==row && tempCellData->col==col) return tempCellData;
61 }
57 return NULL; 62 return NULL;
58} 63}
59 64
60void Sheet::slotCellSelected(int row, int col) 65void Sheet::slotCellSelected(int row, int col)
61{ 66{
62 typeCellData *cellData=findCellData(row, col); 67 typeCellData *cellData=findCellData(row, col);
63 if (cellData) 68 if (cellData)
69 {
64 emit currentDataChanged(cellData->data); 70 emit currentDataChanged(cellData->data);
65 else 71 }else
66 emit currentDataChanged(""); 72 emit currentDataChanged("");
67} 73}
68 74
69typeCellData *Sheet::createCellData(int row, int col) 75typeCellData *Sheet::createCellData(int row, int col)
70{ 76{
71 if (row<0 || col<0) return NULL; 77 if (row<0 || col<0) return NULL;
@@ -85,16 +91,44 @@ typeCellData *Sheet::createCellData(int row, int col)
85void Sheet::slotCellChanged(int row, int col) 91void Sheet::slotCellChanged(int row, int col)
86{ 92{
87 typeCellData *cellData=findCellData(row, col); 93 typeCellData *cellData=findCellData(row, col);
88 if (!cellData) cellData=createCellData(row, col); 94 if (!cellData) cellData=createCellData(row, col);
89 if (cellData) cellData->data=text(row, col); 95 if (cellData) cellData->data=text(row, col);
90 for (cellData=sheetData.first(); cellData; cellData=sheetData.next()) 96 for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
91 setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data)); 97 {
98 // modified by Toussis Manolis koppermind@panafonet.gr
99 // the parser was crashing if there were no closed parenthesis.
100 int w1,ii=0;
101 for(w1=0;w1<=(int)text(row, col).length();w1++)
102 {
103 if(text(row,col)[w1]=='(') ii++;
104 if(text(row,col)[w1]==')') ii--;
105 };
106 if(ii==0) setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
107 //end of modification
108 // old was plain:
109 //setText(cellData->row, cellData->col, dataParser(findCellName(cellData->row, cellData->col), cellData->data));
110 };
92 emit sheetModified(); 111 emit sheetModified();
93} 112}
94 113
114
115void Sheet::ReCalc(void)
116{
117 typeCellData* cellData;
118 for (cellData=sheetData.first(); cellData; cellData=sheetData.next())
119 {
120 //printf("cellchanged:%d, %d\r\n",cellData->row,cellData->col);
121
122 slotCellChanged(cellData->row,cellData->col);
123 };
124};
125
126
127
128
95void Sheet::swapCells(int row1, int col1, int row2, int col2) 129void Sheet::swapCells(int row1, int col1, int row2, int col2)
96{ 130{
97 typeCellData *cellData1=findCellData(row1, col1), *cellData2=findCellData(row2, col2); 131 typeCellData *cellData1=findCellData(row1, col1), *cellData2=findCellData(row2, col2);
98 if (!cellData1) cellData1=createCellData(row1, col1); 132 if (!cellData1) cellData1=createCellData(row1, col1);
99 if (!cellData2) cellData2=createCellData(row2, col2); 133 if (!cellData2) cellData2=createCellData(row2, col2);
100 if (cellData1 && cellData2) 134 if (cellData1 && cellData2)
@@ -115,25 +149,26 @@ QString Sheet::getParameter(const QString &parameters, int paramNo, bool giveErr
115 for (int i=0; i<paramNo; ++i) 149 for (int i=0; i<paramNo; ++i)
116 { 150 {
117 position=params.find(','); 151 position=params.find(',');
118 if (position<0) 152 if (position<0)
119 { 153 {
120 if (giveError) QMessageBox::critical(this, tr("Error"), tr("Too few arguments to function '"+funcName+'\'')); 154 if (giveError) QMessageBox::critical(this, tr("Error"), tr("Too few arguments to function '"+funcName+'\''));
121 return QString(); 155 //printf("params:%s\r\n",parameters.ascii());
156 return QString(NULL);
122 } 157 }
123 params=params.mid(position+1); 158 params=params.mid(position+1);
124 } 159 }
125 position=params.find(','); 160 position=params.find(',');
126 if (position<0) return params; 161 if (position<0) return params;
127 return params.left(position); 162 return params.left(position);
128} 163}
129 164
130bool Sheet::findRange(const QString &variable1, const QString &variable2, int *row1, int *col1, int *row2, int *col2) 165bool Sheet::findRange(const QString &variable1, const QString &variable2, int *row1, int *col1, int *row2, int *col2)
131{ 166{
132 int row, col; 167 int row, col;
133 if (!findRowColumn(variable1, row1, col1, TRUE) || !findRowColumn(variable2, row2, col2, TRUE)) return FALSE; 168 if (!findRowColumn(variable1, row1, col1, FALSE) || !findRowColumn(variable2, row2, col2, FALSE)) return FALSE;
134 if (*row1>*row2) 169 if (*row1>*row2)
135 { 170 {
136 row=*row1; 171 row=*row1;
137 *row1=*row2; 172 *row1=*row2;
138 *row2=row; 173 *row2=row;
139 } 174 }
@@ -156,294 +191,1658 @@ bool Sheet::findRowColumn(const QString &variable, int *row, int *col, bool give
156 } 191 }
157 *row=variable.mid(position).toInt()-1; 192 *row=variable.mid(position).toInt()-1;
158 *col=getHeaderColumn(variable.left(position))-1; 193 *col=getHeaderColumn(variable.left(position))-1;
159 return TRUE; 194 return TRUE;
160} 195}
161 196
162double Sheet::calculateVariable(const QString &variable) 197QString Sheet::calculateVariable(const QString &variable)
163{ 198{
164 bool ok; 199 bool ok;
200 printf("calculateVariable=%s,len=%d\r\n",variable.ascii(),variable.length());
201 if(variable.left(1)=="\"") return QString(variable.mid(1,variable.length()-2));
165 double tempResult=variable.toDouble(&ok); 202 double tempResult=variable.toDouble(&ok);
166 if (ok) return tempResult; 203 if (ok)
204 {
205 if(tempResult!=0.0)
206 {
207 return QString::number(tempResult);
208 }
209 else
210 {
211 if(variable!="0" || variable!="0.0") return QString(variable); // hereis a string variable
212 return QString::number(tempResult);
213 };
214 };
167 215
168 int row, col; 216 int row, col;
169 return (findRowColumn(variable, &row, &col, TRUE) ? dataParser(variable, text(row, col)).toDouble() : 0); 217 if(findRowColumn(variable, &row, &col, FALSE)) return dataParser(variable, text(row,col));
218 //return (findRowColumn(variable, &row, &col, TRUE) ? dataParser(variable, text(row, col)) : 0);
219 return QString(variable);
170} 220}
171 221
222double Sheet::BesselI0(double x)
223{
224 //Returns the modi ed Bessel function I0(x) for any real x.
225 double ax,ans;
226 double y;
227 if ((ax=fabs(x)) < 3.75)
228 {
229 y=x/3.75;
230 y*=y;
231 ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
232 }else
233 {
234 y=3.75/ax;
235 ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 +y*0.392377e-2))))))));
236 }
237 return ans;
238};
239
240double Sheet::BesselI1(double x)
241{
242 double ax,ans;
243 double y;
244 if ((ax=fabs(x)) < 3.75)
245 {
246 y=x/3.75;
247 y*=y;
248 ans=ax*(0.5+y*(0.87890594+y*(0.51498869+y*(0.15084934 +y*(0.2658733e-1+y*(0.301532e-2+y*0.32411e-3))))));
249 } else
250 {
251 y=3.75/ax;
252 ans=0.2282967e-1+y*(-0.2895312e-1+y*(0.1787654e-1 -y*0.420059e-2)); ans=0.39894228+y*(-0.3988024e-1+y*(-0.362018e-2 +y*(0.163801e-2+y*(-0.1031555e-1+y*ans))));
253 ans *= (exp(ax)/sqrt(ax));
254 }
255 return x < 0.0 ? -ans : ans;
256};
257
258double Sheet::BesselI(int n, double x)
259{
260 double ACC=40.0;
261 double BIGNO=1.0e10;
262 double BIGNI=1.0e-10;
263 int j;
264 double bi,bim,bip,tox,ans;
265 if (n < 2) return 0.0;
266 if (x == 0.0) return 0.0; else
267 {
268 tox=2.0/fabs(x);
269 bip=ans=0.0;
270 bi=1.0;
271 for (j=2*(n+(int) sqrt(ACC*n));j>0;j--)
272 {
273 bim=bip+j*tox*bi;
274 bip=bi;
275 bi=bim;
276 if (fabs(bi) > BIGNO)
277 {
278 ans *= BIGNI;
279 bi *= BIGNI;
280 bip *= BIGNI;
281 }
282 if (j == n) ans=bip;
283 }
284 ans *= BesselI0(x)/bi;
285 return x < 0.0 && (n & 1) ? -ans : ans;
286 }
287};
288
289double Sheet::BesselK0(double x)
290{
291 double y,ans;
292 if (x <= 2.0)
293 {
294 y=x*x/4.0;
295 ans=(-log(x/2.0)*BesselI0(x))+(-0.57721566+y*(0.42278420 +y*(0.23069756+y*(0.3488590e-1+y*(0.262698e-2 +y*(0.10750e-3+y*0.74e-5))))));
296 } else
297 {
298 y=2.0/x;
299 ans=(exp(-x)/sqrt(x))*(1.25331414+y*(-0.7832358e-1 +y*(0.2189568e-1+y*(-0.1062446e-1+y*(0.587872e-2 +y*(-0.251540e-2+y*0.53208e-3))))));
300 }
301return ans;
302};
303
304double Sheet::BesselK1(double x)
305{
306 double y,ans;
307 if (x <= 2.0)
308 {
309 y=x*x/4.0;
310 ans=(log(x/2.0)*BesselI1(x))+(1.0/x)*(1.0+y*(0.15443144 +y*(-0.67278579+y*(-0.18156897+y*(-0.1919402e-1 +y*(-0.110404e-2+y*(-0.4686e-4)))))));
311 } else
312 {
313 y=2.0/x;
314 ans=(exp(-x)/sqrt(x))*(1.25331414+y*(0.23498619 +y*(-0.3655620e-1+y*(0.1504268e-1+y*(-0.780353e-2 +y*(0.325614e-2+y*(-0.68245e-3)))))));
315 }
316 return ans;
317};
318
319double Sheet::BesselK(int n, double x)
320{
321 int j;
322 double bk,bkm,bkp,tox;
323 if (n < 2) return 0.0;
324 tox=2.0/x;
325 bkm=BesselK0(x);
326 bk=BesselK1(x);
327 for (j=1;j<n;j++)
328 {
329 bkp=bkm+j*tox*bk;
330 bkm=bk;
331 bk=bkp;
332 }
333 return bk;
334};
335
336double Sheet::BesselJ0(double x)
337{
338 double ax,z;
339 double xx,y,ans,ans1,ans2;
340 if ((ax=fabs(x)) < 8.0)
341 {
342 y=x*x;
343 ans1=57568490574.0+y*(-13362590354.0+y*(651619640.7 +y*(-11214424.18+y*(77392.33017+y*(-184.9052456)))));
344 ans2=57568490411.0+y*(1029532985.0+y*(9494680.718 +y*(59272.64853+y*(267.8532712+y*1.0))));
345 ans=ans1/ans2;
346 } else
347 {
348 z=8.0/ax;
349 y=z*z;
350 xx=ax-0.785398164;
351 ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4 +y*(-0.2073370639e-5+y*0.2093887211e-6)));
352 ans2 = -0.1562499995e-1+y*(0.1430488765e-3 +y*(-0.6911147651e-5+y*(0.7621095161e-6 -y*0.934935152e-7)));
353 ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
354 }
355 return ans;
356};
357
358double Sheet::BesselY0(double x)
359{
360 double z;
361 double xx,y,ans,ans1,ans2;
362 if (x < 8.0)
363 {
364 y=x*x;
365 ans1 = -2957821389.0+y*(7062834065.0+y*(-512359803.6 +y*(10879881.29+y*(-86327.92757+y*228.4622733))));
366 ans2=40076544269.0+y*(745249964.8+y*(7189466.438 +y*(47447.26470+y*(226.1030244+y*1.0))));
367 ans=(ans1/ans2)+0.636619772*BesselJ0(x)*log(x);
368 } else
369 {
370 z=8.0/x;
371 y=z*z;
372 xx=x-0.785398164;
373 ans1=1.0+y*(-0.1098628627e-2+y*(0.2734510407e-4 +y*(-0.2073370639e-5+y*0.2093887211e-6)));
374 ans2 = -0.1562499995e-1+y*(0.1430488765e-3 +y*(-0.6911147651e-5+y*(0.7621095161e-6 +y*(-0.934945152e-7))));
375 ans=sqrt(0.636619772/x)*(sin(xx)*ans1+z*cos(xx)*ans2);
376 }
377 return ans;
378};
379
380double Sheet::BesselJ1(double x)
381{
382 double ax,z;
383 double xx,y,ans,ans1,ans2;
384 if ((ax=fabs(x)) < 8.0)
385 {
386 y=x*x;
387 ans1=x*(72362614232.0+y*(-7895059235.0+y*(242396853.1 +y*(-2972611.439+y*(15704.48260+y*(-30.16036606))))));
388 ans2=144725228442.0+y*(2300535178.0+y*(18583304.74 +y*(99447.43394+y*(376.9991397+y*1.0))));
389 ans=ans1/ans2;
390 } else
391 {
392 z=8.0/ax; y=z*z; xx=ax-2.356194491;
393 ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 +y*(0.2457520174e-5+y*(-0.240337019e-6))));
394 ans2=0.04687499995+y*(-0.2002690873e-3 +y*(0.8449199096e-5+y*(-0.88228987e-6 +y*0.105787412e-6)));
395 ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
396 if (x < 0.0) ans = -ans;
397 }
398 return ans;
399};
400
401double Sheet::BesselY1(double x)
402{
403 double z;
404 double xx,y,ans,ans1,ans2;
405 if (x < 8.0)
406 {
407 y=x*x;
408 ans1=x*(-0.4900604943e13+y*(0.1275274390e13 +y*(-0.5153438139e11+y*(0.7349264551e9 +y*(-0.4237922726e7+y*0.8511937935e4)))));
409 ans2=0.2499580570e14+y*(0.4244419664e12 +y*(0.3733650367e10+y*(0.2245904002e8 +y*(0.1020426050e6+y*(0.3549632885e3+y)))));
410 ans=(ans1/ans2)+0.636619772*(BesselJ1(x)*log(x)-1.0/x);
411 } else
412 {
413 z=8.0/x;
414 y=z*z;
415 xx=x-2.356194491;
416 ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4 +y*(0.2457520174e-5+y*(-0.240337019e-6))));
417 ans2=0.04687499995+y*(-0.2002690873e-3 +y*(0.8449199096e-5+y*(-0.88228987e-6 +y*0.105787412e-6)));
418 ans=sqrt(0.636619772/x)*(sin(xx)*ans1+z*cos(xx)*ans2);
419 }
420 return ans;
421};
422
423double Sheet::BesselY(int n, double x)
424{
425 int j;
426 double by,bym,byp,tox;
427 if (n < 2) return 0.0;
428 tox=2.0/x;
429 by=BesselY1(x);
430 bym=BesselY0(x);
431 for (j=1;j<n;j++)
432 {
433 byp=j*tox*by-bym;
434 bym=by;
435 by=byp;
436 }
437 return by;
438};
439
440double Sheet::BesselJ(int n, double x)
441{
442 double ACC=40.0;
443 double BIGNO=1.0e10;
444 double BIGNI=1.0e-10;
445 int j,jsum,m;
446 double ax,bj,bjm,bjp,sum,tox,ans;
447 if (n < 2) return 0.0;
448 ax=fabs(x);
449 if (ax == 0.0) return 0.0;
450 else if (ax > (double) n)
451 {
452 tox=2.0/ax;
453 bjm=BesselJ0(ax);
454 bj=BesselJ1(ax);
455 for (j=1;j<n;j++)
456 {
457 bjp=j*tox*bj-bjm;
458 bjm=bj;
459 bj=bjp;
460 }
461 ans=bj;
462 } else
463 {
464 tox=2.0/ax;
465 m=2*((n+(int) sqrt(ACC*n))/2);
466 jsum=0;
467 bjp=ans=sum=0.0;
468 bj=1.0;
469 for (j=m;j>0;j--)
470 {
471 bjm=j*tox*bj-bjp;
472 bjp=bj;
473 bj=bjm;
474 if (fabs(bj) > BIGNO)
475 {
476 bj *= BIGNI;
477 bjp *= BIGNI;
478 ans *= BIGNI;
479 sum *= BIGNI;
480 }
481 if (jsum) sum += bj;
482 jsum=!jsum;
483 if (j == n) ans=bjp;
484 }
485 sum=2.0*sum-bj;
486 ans /= sum;
487 }
488 return x < 0.0 && (n & 1) ? -ans : ans;
489};
490
491double Sheet::GammaLn(double xx)
492{
493 double x,y,tmp,ser;
494 static double cof[6]={76.18009172947146,-86.50532032941677, 24.01409824083091,-1.231739572450155, 0.1208650973866179e-2,-0.5395239384953e-5};
495 int j;
496 y=x=xx;
497 tmp=x+5.5;
498 tmp -= (x+0.5)*log(tmp);
499 ser=1.000000000190015;
500 for (j=0;j<=5;j++) ser += cof[j]/++y;
501 return -tmp+log(2.5066282746310005*ser/x);
502};
503
504double Sheet::Factorial(double n)
505{
506 if (n < 0) return 0.0;
507 if (n > 100) return 0.0;
508 return exp(GammaLn(n+1.0));
509};
510
511double Sheet::GammaP(double a, double x)
512{
513// returns GammaP(a,x)
514//void gcf(float *gammcf, float a, float x, float *gln);
515//void gser(float *gamser, float a, float x, float *gln);
516 double gamser,gammcf,gln;
517 if (x < 0.0 || a <= 0.0) return 0.0;//error
518 if (x < (a+1.0))
519 {
520 GammaSeries(&gamser,a,x,&gln);
521 return gamser;
522 }else
523 {
524 GammaContinuedFraction(&gammcf,a,x,&gln);
525 return 1.0-gammcf;
526 }
527};
528
529double Sheet::GammaQ(double a,double x)
530{
531 //returns GammaQ(a,x)=1.0 - GammaP(a,x);
532 return (1.0-GammaP(a,x));
533};
534
535
536void Sheet::GammaSeries(double *gamser, double a, double x, double *gln)
537{
538 double EPS=3.0e-7;
539 int ITMAX=100;
540 int n;
541 double sum,del,ap;
542 *gln=GammaLn(a);
543 if (x <= 0.0)
544 {
545 if (x < 0.0) return;//error
546 *gamser=0.0;
547 return;
548 } else
549 {
550 ap=a;
551 del=sum=1.0/a;
552 for (n=1;n<=ITMAX;n++)
553 {
554 ++ap;
555 del *= x/ap;
556 sum += del;
557 if (fabs(del) < fabs(sum)*EPS)
558 {
559 *gamser=sum*exp(-x+a*log(x)-(*gln));
560 return;
561 }
562 } return;
563 return;
564 }
565};
566
567
568void Sheet::GammaContinuedFraction(double *gammcf, double a, double x, double *gln)
569{
570 double EPS=3.0e-7;
571 double FPMIN=1.0e-30;
572 int ITMAX=100;
573 int i;
574 double an,b,c,d,del,h;
575 *gln=GammaLn(a);
576 b=x+1.0-a;
577 c=1.0/FPMIN;
578 d=1.0/b; h=d;
579 for (i=1;i<=ITMAX;i++)
580 {
581 an = -i*(i-a);
582 b += 2.0; d=an*d+b;
583 if (fabs(d) < FPMIN) d=FPMIN;
584 c=b+an/c;
585 if (fabs(c) < FPMIN) c=FPMIN;
586 d=1.0/d; del=d*c; h *= del;
587 if (fabs(del-1.0) < EPS) break;
588 }
589 if (i > ITMAX) return;
590 *gammcf=exp(-x+a*log(x)-(*gln))*h;
591};
592
593double Sheet::ErrorFunction(double x)
594{
595 return x < 0.0 ? -GammaP(0.5,x*x) : GammaP(0.5,x*x);
596};
597
598double Sheet::ErrorFunctionComplementary(double x)
599{
600 return x < 0.0 ? 1.0+GammaP(0.5,x*x) : GammaQ(0.5,x*x);
601};
602
603double Sheet::Beta(double z, double w)
604{
605 return exp(GammaLn(z)+GammaLn(w)-GammaLn(z+w));
606};
607
608
609double Sheet::BetaContinuedFraction(double a, double b, double x)
610{
611 int MAXIT=100;
612 double EPS=3.0e-7;
613 double FPMIN=1.0e-30;
614 int m,m2;
615 double aa,c,d,del,h,qab,qam,qap;
616 qab=a+b;
617 qap=a+1.0; qam=a-1.0; c=1.0;
618 d=1.0-qab*x/qap;
619 if (fabs(d) < FPMIN) d=FPMIN;
620 d=1.0/d; h=d;
621 for (m=1;m<=MAXIT;m++)
622 {
623 m2=2*m; aa=m*(b-m)*x/((qam+m2)*(a+m2));
624 d=1.0+aa*d;
625 if (fabs(d) < FPMIN) d=FPMIN;
626 c=1.0+aa/c;
627 if (fabs(c) < FPMIN) c=FPMIN;
628 d=1.0/d; h *= d*c;
629 aa = -(a+m)*(qab+m)*x/((a+m2)*(qap+m2)); d=1.0+aa*d;
630 if (fabs(d) < FPMIN) d=FPMIN;
631 c=1.0+aa/c;
632 if (fabs(c) < FPMIN) c=FPMIN; d=1.0/d;
633 del=d*c; h *= del;
634 if (fabs(del-1.0) < EPS) break;
635 }
636 if (m > MAXIT) return 0.0;
637 return h;
638};
639
640double Sheet::BetaIncomplete(double a, double b, double x)
641{
642 double bt;
643 if (x < 0.0 || x > 1.0) return 0.0;
644 if (x == 0.0 || x == 1.0) bt=0.0; else
645 bt=exp(GammaLn(a+b)-GammaLn(a)-GammaLn(b)+a*log(x)+b*log(1.0-x));
646 if (x < (a+1.0)/(a+b+2.0)) return bt*BetaContinuedFraction(a,b,x)/a; else
647 return 1.0-bt*BetaContinuedFraction(b,a,1.0-x)/b;
648};
649
650
651
172double Sheet::functionSum(const QString &param1, const QString &param2) 652double Sheet::functionSum(const QString &param1, const QString &param2)
173{ 653{
174 int row1, col1, row2, col2, row, col; 654 int row1, col1, row2, col2, row, col;
655 double result=0, tempResult;
656 bool ok;
657 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
658 {
659 for (row=row1; row<=row2; ++row)
660 for (col=col1; col<=col2; ++col)
661 {
662 tempResult=text(row, col).toDouble(&ok);
663 if (ok) result+=tempResult;
664 }
665 return result;
666 }else
667 {
668 double d1=0,d2=0;
669 d1=calculateVariable(param1).toDouble(&ok);
670 d2=calculateVariable(param2).toDouble(&ok);
671 return(d1+d2);
672 };
673 return 0;
674}
675
676QString Sheet::functionIndex(const QString &param1, const QString &param2, int indx)
677{
678 int row1, col1, row2, col2, row, col;
175 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0; 679 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
680 int ii=1;
681 for (col=col1; col<=col2; ++col)
682 for (row=row1; row<=row2; ++row)
683 {
684 if(ii==indx) return text(row,col);
685 ii++;
686 }
687 return QString("");
688}
689
690
176 691
692double Sheet::functionVariancePopulation(const QString &param1, const QString &param2)
693{
694 int row1, col1, row2, col2, row, col;
695 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
696 double avg1=functionAvg(param1,param2);
177 double result=0, tempResult; 697 double result=0, tempResult;
698 int count1=0;
178 bool ok; 699 bool ok;
179 for (row=row1; row<=row2; ++row) 700 for (row=row1; row<=row2; ++row)
180 for (col=col1; col<=col2; ++col) 701 for (col=col1; col<=col2; ++col)
181 { 702 {
182 tempResult=text(row, col).toDouble(&ok); 703 tempResult=text(row, col).toDouble(&ok);
183 if (ok) result+=tempResult; 704 if (ok) { result=result + (tempResult - avg1)*(tempResult - avg1); count1++;};
184 } 705 }
185 706 if(count1>0) result=result/double(count1); else result=0.0;
186 return result; 707 return result;
187} 708};
188 709
189double Sheet::functionMin(const QString &param1, const QString &param2) 710double Sheet::functionVariance(const QString &param1, const QString &param2)
190{ 711{
191 int row1, col1, row2, col2, row, col; 712 int row1, col1, row2, col2, row, col;
192 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0; 713 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
714 double avg1=functionAvg(param1,param2);
715 double result=0, tempResult;
716 int count1=0;
717 bool ok;
718 for (row=row1; row<=row2; ++row)
719 for (col=col1; col<=col2; ++col)
720 {
721 tempResult=text(row, col).toDouble(&ok);
722 if (ok) { result=result + (tempResult - avg1)*(tempResult - avg1); count1++;};
723 }
724 if(count1>1) result=result/double(count1-1); else result=0.0;
725 return result;
726};
193 727
194 double min=0, tempMin; 728double Sheet::functionSkew(const QString &param1, const QString &param2)
195 bool ok, init=FALSE; 729{
730 int row1, col1, row2, col2, row, col;
731 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
732 double avg1=functionAvg(param1,param2);
733 double var1=sqrt(functionVariancePopulation(param1,param2));
734 if(var1==0.0) return 0.0;
735 double result=0, tempResult;
736 int count1=0;
737 bool ok;
196 for (row=row1; row<=row2; ++row) 738 for (row=row1; row<=row2; ++row)
197 for (col=col1; col<=col2; ++col) 739 for (col=col1; col<=col2; ++col)
198 { 740 {
199 tempMin=text(row, col).toDouble(&ok); 741 tempResult=text(row, col).toDouble(&ok);
200 if (ok && (!init || tempMin<min)) 742 if (ok)
201 { 743 {
202 min=tempMin; 744 result=result + (tempResult - avg1)*(tempResult - avg1)*(tempResult - avg1)/(var1*var1*var1);
203 init=TRUE; 745 count1++;
204 } 746 };
205 } 747 }
748 if(count1>0) result=result/double(count1); else result=0.0;
749 return result;
750};
206 751
207 return min; 752double Sheet::functionKurt(const QString &param1, const QString &param2)
208}
209
210double Sheet::functionMax(const QString &param1, const QString &param2)
211{ 753{
212 int row1, col1, row2, col2, row, col; 754 int row1, col1, row2, col2, row, col;
213 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0; 755 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
214 756 double avg1=functionAvg(param1,param2);
215 double max=0, tempMax; 757 double var1=sqrt(functionVariancePopulation(param1,param2));
216 bool ok, init=FALSE; 758 if(var1==0.0) return 0.0;
759 double result=0, tempResult;
760 int count1=0;
761 bool ok;
217 for (row=row1; row<=row2; ++row) 762 for (row=row1; row<=row2; ++row)
218 for (col=col1; col<=col2; ++col) 763 for (col=col1; col<=col2; ++col)
219 { 764 {
220 tempMax=text(row, col).toDouble(&ok); 765 tempResult=text(row, col).toDouble(&ok);
221 if (ok && (!init || tempMax>max)) 766 if (ok)
222 { 767 {
223 max=tempMax; 768 result=result + (tempResult - avg1)*(tempResult - avg1)*
224 init=TRUE; 769 (tempResult - avg1)*(tempResult - avg1)/(var1*var1*var1*var1);
225 } 770 count1++;
771 };
226 } 772 }
773 if(count1>0) result=result/double(count1)-3.0; else result=0.0;
774 return result;
775};
776
777
778
779double Sheet::functionSumSQ(const QString &param1, const QString &param2)
780{
781 int row1, col1, row2, col2, row, col;
782 double result=0, tempResult;
783 bool ok;
784 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
785 {
786 for (row=row1; row<=row2; ++row)
787 for (col=col1; col<=col2; ++col)
788 {
789 tempResult=text(row, col).toDouble(&ok);
790 if (ok) result+=tempResult*tempResult;
791 }
792 return result;
793 }else
794 {
795 double d1=0,d2=0;
796 d1=calculateVariable(param1).toDouble(&ok);
797 d2=calculateVariable(param2).toDouble(&ok);
798 return(d1*d1+d2*d2);
799 };
800 return 0;
801}
802
227 803
228 return max; 804
805double Sheet::functionMin(const QString &param1, const QString &param2)
806{
807 int row1, col1, row2, col2, row, col;
808 double min=0, tempMin;
809 bool ok, init=FALSE;
810 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
811 {
812 for (row=row1; row<=row2; ++row)
813 for (col=col1; col<=col2; ++col)
814 {
815 tempMin=text(row, col).toDouble(&ok);
816 if (ok && (!init || tempMin<min))
817 {
818 min=tempMin;
819 init=TRUE;
820 }
821 }
822 return min;
823 }else
824 {
825 double d1=0,d2=0;
826 d1=calculateVariable(param1).toDouble(&ok);
827 d2=calculateVariable(param2).toDouble(&ok);
828 if(d1<d2) return(d1); else return(d2);
829 };
830 return 0;
831}
832
833double Sheet::functionMax(const QString &param1, const QString &param2)
834{
835 int row1, col1, row2, col2, row, col;
836 double max=0, tempMax;
837 bool ok, init=FALSE;
838 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
839 {
840 for (row=row1; row<=row2; ++row)
841 for (col=col1; col<=col2; ++col)
842 {
843 tempMax=text(row, col).toDouble(&ok);
844 if (ok && (!init || tempMax>max))
845 {
846 max=tempMax;
847 init=TRUE;
848 }
849 };
850 return max;
851 }else
852 {
853 double d1=0,d2=0;
854 d1=calculateVariable(param1).toDouble(&ok);
855 d2=calculateVariable(param2).toDouble(&ok);
856 if(d1>d2) return(d1); else return(d2);
857 };
858 return 0;
229} 859}
230 860
231double Sheet::functionAvg(const QString &param1, const QString &param2) 861double Sheet::functionAvg(const QString &param1, const QString &param2)
232{ 862{
233 double resultSum=functionSum(param1, param2), resultCount=functionCount(param1, param2); 863 double resultSum=functionSum(param1, param2), resultCount=functionCount(param1, param2);
234 return (resultCount>0 ? resultSum/resultCount : 0); 864 return (resultCount>0 ? resultSum/resultCount : 0);
235} 865}
236 866
237double Sheet::functionCount(const QString &param1, const QString &param2) 867double Sheet::functionCount(const QString &param1, const QString &param2)
238{ 868{
239 int row1, col1, row2, col2, row, col; 869 int row1, col1, row2, col2, row, col;
240 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0; 870 int divider=0;
871 bool ok;
872 if (findRange(param1, param2, &row1, &col1, &row2, &col2))
873 {
874 for (row=row1; row<=row2; ++row)
875 for (col=col1; col<=col2; ++col)
876 {
877 text(row, col).toDouble(&ok);
878 if (ok) ++divider;
879 };
880 return divider;
881 }else
882 {
883 double d1=0,d2=0;int ii=0;
884 d1=calculateVariable(param1).toDouble(&ok);
885 if (ok) ii++;
886 d2=calculateVariable(param2).toDouble(&ok);
887 if (ok) ii++;
888 return(ii);
889 };
890 return 0;
891}
241 892
893double Sheet::functionCountIf(const QString &param1, const QString &param2, const QString &param3)
894{
895 int row1, col1, row2, col2, row, col;
896 if (!findRange(param1, param2, &row1, &col1, &row2, &col2)) return 0;
897 //same as count except check if each field is equal to param3
242 int divider=0; 898 int divider=0;
899 QString s2;
243 bool ok; 900 bool ok;
901 s2=calculateVariable(param3);
244 for (row=row1; row<=row2; ++row) 902 for (row=row1; row<=row2; ++row)
245 for (col=col1; col<=col2; ++col) 903 for (col=col1; col<=col2; ++col)
246 { 904 {
247 text(row, col).toDouble(&ok); 905 text(row, col).toDouble(&ok);
248 if (ok) ++divider; 906 if (ok && (s2==text(row,col)) ) ++divider;
249 } 907 }
250
251 return divider; 908 return divider;
252} 909}
253 910
254double Sheet::calculateFunction(const QString &function, const QString &parameters) 911
912QString Sheet::calculateFunction(const QString &function, const QString &parameters, int NumOfParams)
255{ 913{
914 bool ok;
915 double val1=0.0,val2=0.0,val3=0.0;
916 long int vali=0;
917 int w1,w2;
918 int row,col;
919 QString s1,s2;
920//basic functions
256 if (function=="+") 921 if (function=="+")
257 return calculateVariable(getParameter(parameters, 0))+calculateVariable(getParameter(parameters, 1)); 922 {
923 s1=calculateVariable(getParameter(parameters, 0));
924 s2=calculateVariable(getParameter(parameters, 1));
925 val1=s1.toDouble(&ok)+s2.toDouble(&ok);
926 return QString::number(val1);
927
928 };
258 if (function=="-") 929 if (function=="-")
259 return calculateVariable(getParameter(parameters, 0))-calculateVariable(getParameter(parameters, 1)); 930 {
931 s1=calculateVariable(getParameter(parameters, 0));
932 s2=calculateVariable(getParameter(parameters, 1));
933 val1=s1.toDouble(&ok)-s2.toDouble(&ok);
934 return QString::number(val1);
935 };
260 if (function=="*") 936 if (function=="*")
261 return calculateVariable(getParameter(parameters, 0))*calculateVariable(getParameter(parameters, 1)); 937 {
938 val1=calculateVariable(
939 getParameter(parameters, 0)).toDouble(&ok)
940 *calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
941 return QString::number(val1);
942 };
262 if (function=="/") 943 if (function=="/")
263 return calculateVariable(getParameter(parameters, 0))/calculateVariable(getParameter(parameters, 1));
264 if (function=="SUM")
265 return functionSum(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
266 if (function=="COUNT")
267 return functionCount(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
268 if (function=="MIN")
269 return functionMin(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
270 if (function=="MAX")
271 return functionMax(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
272 if (function=="AVG")
273 return functionAvg(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
274 if (function=="ABS")
275 return fabs(calculateVariable(getParameter(parameters, 0, TRUE, function)));
276 if (function=="SIN")
277 return sin(calculateVariable(getParameter(parameters, 0, TRUE, function)));
278 if (function=="COS")
279 return cos(calculateVariable(getParameter(parameters, 0, TRUE, function)));
280 if (function=="TAN")
281 return tan(calculateVariable(getParameter(parameters, 0, TRUE, function)));
282 if (function=="ATAN")
283 return atan(calculateVariable(getParameter(parameters, 0, TRUE, function)));
284 if (function=="ATAN2")
285 return atan2(calculateVariable(getParameter(parameters, 0, TRUE, function)), calculateVariable(getParameter(parameters, 1, TRUE, function)));
286 if (function=="ASIN")
287 return asin(calculateVariable(getParameter(parameters, 0, TRUE, function)));
288 if (function=="ACOS")
289 return acos(calculateVariable(getParameter(parameters, 0, TRUE, function)));
290 if (function=="EXP")
291 return exp(calculateVariable(getParameter(parameters, 0, TRUE, function)));
292 if (function=="LOG")
293 return log(calculateVariable(getParameter(parameters, 0, TRUE, function)));
294 if (function=="POW")
295 return pow(calculateVariable(getParameter(parameters, 0, TRUE, function)), calculateVariable(getParameter(parameters, 1, TRUE, function)));
296 return 0;
297}
298
299int Sheet::getOperatorPriority(char oper)
300{
301 switch (oper)
302 { 944 {
303 case '+': 945 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
304 case '-': 946 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
305 return 1; 947 if(val2==0.0) return QString("Err101");
306 948 val1=val1/val2;
307 case '*': 949 return QString::number(val1);
308 case '/': 950 };
309 return 2; 951 if (function==">")
310 } 952 {
311 return 0; 953 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
312} 954 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
955 if(val1>val2) return QString::number(1); else return QString::number(0);
956 };
957 if (function=="<")
958 {
959 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
960 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
961 if(val1<val2) return QString::number(1); else return QString::number(0);
962 };
963 if (function==">=")
964 {
965 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
966 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
967 if(val1>=val2) return QString::number(1); else return QString::number(0);
968 };
969 if (function=="<=")
970 {
971 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
972 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
973 if(val1<=val2) return QString::number(1); else return QString::number(0);
974 };
975 if (function=="!=")
976 {
977 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
978 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
979 if(val1!=val2) return QString::number(1); else return QString::number(0);
980 };
981 if (function=="=="||function=="=")
982 {
983 val1=calculateVariable(getParameter(parameters, 0)).toDouble(&ok);
984 val2=calculateVariable(getParameter(parameters, 1)).toDouble(&ok);
985 if(val1==val2) return QString::number(1); else return QString::number(0);
986 };
987
988 //LOGICAL / INFO
989 if (function=="ISBLANK")
990 {
991 if(findRowColumn(getParameter(parameters, 0), &row, &col, FALSE))
992 {
993 if(text(row,col).length()==0) val1=1; else val1=0;
994 }else
995 {
996 if(findRowColumn(calculateVariable(getParameter(parameters, 0)), &row,&col, FALSE))
997 {
998 if(text(row,col).length()==0) val1=1; else val1=0;
999 }else
1000 {
1001 val1=0;
1002 };
1003 };
1004 return QString::number(val1);
1005 };
1006
1007
1008 if (function=="ISNUMBER")
1009 {
1010 if(findRowColumn(getParameter(parameters, 0, TRUE, function), &row, &col, FALSE))
1011 {
1012 val1=text(row,col).toDouble(&ok);
1013 if(ok) val1=1; else val1=0;
1014 }else
1015 {
1016 if(findRowColumn(calculateVariable(getParameter(parameters, 0, TRUE, function)), &row,&col, FALSE))
1017 {
1018 val1=text(row,col).toDouble(&ok);
1019 if(ok) val1=1; else val1=0;
1020 }else
1021 {
1022 val1=0;
1023 };
1024 };
1025 return QString::number(val1);
1026 };
1027 if (function=="AND")
1028 {
1029 vali=calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok)
1030 & calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1031 return QString::number(vali);
1032 };
1033 if (function=="OR")
1034 {
1035 vali=calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok)
1036 | calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1037 return QString::number(vali);
1038 };
1039 if (function=="NOT")
1040 {
1041 vali=!calculateVariable(getParameter(parameters, 0, TRUE, function)).toInt(&ok);
1042 return QString::number(vali);
1043 };
1044
1045 // MATHEMATICAL FUNCTIONS
1046 if (function=="ABS")
1047 {
1048 val1=fabs(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1049 return QString::number(val1);
1050 };
1051 if (function=="ACOS")
1052 {
1053 val1=acos(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1054 return QString::number(val1);
1055 };
1056 if (function=="ACOSH")
1057 {
1058 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1059 if(val1<1.0) return QString::number(0);
1060 val1=acosh(val1);
1061 return QString::number(val1);
1062 };
1063 if (function=="ASIN")
1064 {
1065 val1=asin(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1066 return QString::number(val1);
1067 };
1068 if (function=="ASINH")
1069 {
1070 val1=asinh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1071 return QString::number(val1);
1072 };
1073 if (function=="ATAN")
1074 {
1075 val1=atan(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1076 return QString::number(val1);
1077 };
1078 if (function=="ATAN2")
1079 {
1080 val1=atan2(calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok),
1081 calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1082 return QString::number(val1);
1083 };
1084 if (function=="ATANH")
1085 {
1086 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1087 if(val1<=-1.0 || val1>=1.0) return QString("Err101");
1088 val1=atanh(val1);
1089 return QString::number(val1);
1090 };
1091 if (function=="CEILING")
1092 {
1093 // rounds up param1 to specified accuracy param2
1094 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1095 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1096 if(val2==0.0) return QString::number(val1);
1097 val1=ceil(val1/val2)*val2;
1098 return QString::number(val1);
1099 };
1100 if (function=="COS")
1101 {
1102 val1=cos(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1103 return QString::number(val1);
1104 };
1105 if (function=="COSH")
1106 {
1107 val1=cosh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1108 return QString::number(val1);
1109 };
1110 if (function=="DEGREES")
1111 {
1112 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok)*180.0/M_PI;
1113 return QString::number(val1);
1114 };
1115 if (function=="EXP")
1116 {
1117 val1=exp(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1118 return QString::number(val1);
1119 };
1120 if (function=="FACT")
1121 {
1122 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1123 val2=Factorial(val1);
1124 return QString::number(val2);
1125 };
1126 if (function=="FLOOR")
1127 {
1128 // rounds down param1 to specified accuracy param2
1129 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1130 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1131 if(val2==0.0) return QString::number(val1);
1132 val1=floor(val1/val2)*val2;
1133 return QString::number(val1);
1134 };
1135 if (function=="INT")
1136 {
1137 // rounds down param1
1138 val1=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1139 return QString::number(val1);
1140 };
1141 if (function=="EVEN")
1142 {
1143 //converts param1 to even
1144 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1145 if(vali % 2 !=0) val1=vali+1; else val1=vali;
1146 return QString::number(val1);
1147 };
1148 if (function=="ODD")
1149 {
1150 //converts param1 to odd
1151 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1152 if(vali % 2 !=0) val1=vali; else val1=vali+1;
1153 return QString::number(val1);
1154 };
1155 if (function=="ISEVEN")
1156 {
1157 //Is Even param1?
1158 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1159 if(vali % 2 == 0) val1=1; else val1=0;
1160 return QString::number(val1);
1161 };
1162 if (function=="ISODD")
1163 {
1164 //Is odd param1?
1165 vali=int(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1166 if(vali % 2 == 0) val1=0; else val1=1;
1167 return QString::number(val1);
1168 };
1169 if (function=="LN")
1170 {
1171 // returns the natural logarithm of param1
1172 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1173 if(val1<=0.0) return QString("Err101");
1174 val1=log(val1);
1175 return QString::number(val1);
1176 };
1177 if (function=="LOG10")
1178 {
1179 // returns the base-10 logarithm of param1
1180 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1181 if(val1<=0.0) return QString("Err101");
1182 val1=log10(val1);
1183 return QString::number(val1);
1184 };
1185 if (function=="LOG")
1186 {
1187 // return the base-param2 logarithm of param1
1188 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1189 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1190 if(val1<=0.0 || val2<=0.0 ) return QString("Err101");
1191 val1=log(val1)/log(val2);
1192 return QString::number(val1);
1193 };
1194 if (function=="MOD")
1195 {
1196 // return the modulus of param1/param2
1197 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1198 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1199 if(val2==0.0) return QString("Err101");
1200 val1=(int(val1) % int(val2));
1201 return QString::number(val1);
1202 };
1203 if (function=="POWER")
1204 {
1205 // return the param1^param2
1206 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1207 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1208 if(val1<0.0 && (floor(val2)!=val2)) return QString("Err101");
1209 val1=pow(val1,val2);
1210 return QString::number(val1);
1211 };
1212 if (function=="PI")
1213 {
1214 return QString::number(M_PI);
1215 };
1216 if (function=="RADIANS")
1217 {
1218 // param1 deg->rad
1219 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok)*M_PI/180.0;
1220 return QString::number(val1);
1221 };
1222 if (function=="RAND")
1223 {
1224 // retuns random number 0>x>1
1225 srand((unsigned int)time((time_t *)NULL));
1226 val1=double(rand())/double(RAND_MAX);
1227 return QString::number(val1);
1228 };
1229 if (function=="RANDBETWEEN")
1230 {
1231 // returns random number between param1>x>param2
1232 //TOFIX: this is not ok because I think results is always int related.
1233 srand((unsigned int)time((time_t *)NULL));
1234 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1235 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1236 val1=fmod(double(rand()),(val2-val1))+val1;
1237 return QString::number(val1);
1238 };
1239 if (function=="ROUND")
1240 {
1241 // rounds down param1 to specified digits param2 (positive decimal digits)
1242 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1243 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1244 val2=pow(10.0,-val2);
1245 val1=floor(val1/val2)*val2;
1246 return QString::number(val1);
1247 };
1248 if (function=="SIGN")
1249 {
1250 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1251 if(val1>=0.0) return QString::number(1.0); else return QString::number(-1.0);
1252 };
1253 if (function=="CHGSGN")//changes sign (for unary operator)
1254 {
1255 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1256 return QString::number((-1.0)*val1);
1257 };
1258 if (function=="SIN")
1259 {
1260 val1=sin(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1261 return QString::number(val1);
1262 };
1263 if (function=="SINH")
1264 {
1265 val1=sinh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1266 return QString::number(val1);
1267 };
1268 if (function=="TAN")
1269 {
1270 val1=tan(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1271 return QString::number(val1);
1272 };
1273 if (function=="TANH")
1274 {
1275 val1=tanh(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1276 return QString::number(val1);
1277 };
1278 if (function=="SQRT")
1279 {
1280 val1=sqrt(calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok));
1281 return QString::number(val1);
1282 };
1283
1284
1285// STRING FUNCTIONS
1286 if (function=="CONCATENATE")
1287 {
1288 // concatenates strings together
1289 w1=0;
1290 s1="";
1291 while(getParameter(parameters, w1, FALSE, function)!="") //parse all params;
1292 {
1293 s1=s1+calculateVariable(getParameter(parameters, w1));
1294 w1++;
1295 };
1296 return QString(s1);
1297 };
1298 if (function=="EXACT")
1299 {
1300 // compare two string if they are exactly the same
1301 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1302 s2=calculateVariable(getParameter(parameters, 1, TRUE, function));
1303 if(s1==s2) return QString::number(1); else return QString::number(0);
1304 };
1305 if (function=="FIND")
1306 {
1307 // finds param1 in param2 from pos param3 and after
1308 // returns -1 if not found
1309 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1310 s2=calculateVariable(getParameter(parameters, 1, TRUE, function));
1311 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
1312 val1=s2.find(s1,vali);
1313 return QString::number(val1);
1314 };
1315 if (function=="LEFT")
1316 {
1317 // returns the param2 left chars from param1 string
1318 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1319 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1320 s2=s1.left(vali);
1321 return QString(s2);
1322 };
1323 if (function=="LEN")
1324 {
1325 // return the length of a string(param1)
1326 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1327 return QString::number(s1.length());
1328 };
1329 if (function=="MID")
1330 {
1331 // returns the mid word of string param1 with start param2 and len param3
1332 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1333 w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1334 w2=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
1335 s2=s1.mid(w1,w2);
1336 return QString(s2);
1337 };
1338 if (function=="REPLACE")
1339 {
1340 //replace in param1 text in pos param2 and length param3 to newtext param4
1341 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1342 w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1343 w2=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
1344 s2=calculateVariable(getParameter(parameters, 3, TRUE, function));
1345 if(w1<0 || w2<0) return QString(s1);
1346 s1=s1.left(w2-1)+s2+s1.right(s1.length()-w1-w2);
1347 return QString(s1);
1348 };
1349 if (function=="REPT")
1350 {
1351 //repeats param1 string param2 times
1352 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1353 w1=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1354 for(w2=1;w2<=w1;w2++)
1355 {
1356 s2=s2.append(s1);
1357 };
1358 return QString(s2);
1359 };
1360 if (function=="RIGHT")
1361 {
1362 // returns the param2 right chars from param1 string
1363 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1364 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1365 s2=s1.right(vali);
1366 return QString(s2);
1367 };
1368 if (function=="UPPER")
1369 {
1370 // returns the upper param1 string
1371 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1372 s1=s1.upper();
1373 return QString(s1);
1374 };
1375 if (function=="LOWER")
1376 {
1377 // returns the lower param1 string
1378 s1=calculateVariable(getParameter(parameters, 0, TRUE, function));
1379 s1=s1.lower();
1380 return QString(s1);
1381 };
1382 if (function=="IF")
1383 {
1384 //usage: IF(param1,param2,param3)
1385 //returns param4 if true(param1)/ param5 if false(param1)
1386 val1=getParameter(parameters, 0, TRUE, function).toDouble(&ok);
1387 if(val1==1.0)
1388 {
1389 s1=calculateVariable(getParameter(parameters, 1, TRUE, function));
1390 return QString(s1);
1391 }else
1392 {
1393 s1=calculateVariable(getParameter(parameters, 2, TRUE, function));
1394 return QString(s1);
1395 };
1396 };
1397 if (function=="SUM")
1398 {
1399 //NumOfParams
1400 val2=0.0;
1401 for(w1=1;w1<=(NumOfParams/2);w1++)
1402 {
1403 val1=functionSum(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
1404 val2=val2+val1;
1405 };
1406 if(NumOfParams%2==1)
1407 {
1408 val2=val2+calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
1409 };
1410 return QString::number(val2);
1411 };
1412 if (function=="INDEX")
1413 {
1414 s1=functionIndex(getParameter(parameters,0,TRUE,function), getParameter(parameters, 1, TRUE, function), getParameter(parameters,2,TRUE,function).toInt(&ok));
1415 return QString(s1);
1416 };
1417 if (function=="SUMSQ")
1418 {
1419 //NumOfParams
1420 val2=0.0;
1421 for(w1=1;w1<=(NumOfParams/2);w1++)
1422 {
1423 val1=functionSumSQ(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
1424 val2=val2+val1;
1425 };
1426 if(NumOfParams%2==1)
1427 {
1428 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
1429 val2=val2+val1*val1;
1430 };
1431 return QString::number(val2);
1432 };
1433 if (function=="COUNT")
1434 {
1435 //NumOfParams
1436 val2=0.0;
1437 for(w1=1;w1<=(NumOfParams/2);w1++)
1438 {
1439 val1=functionCount(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
1440 val2=val2+val1;
1441 };
1442 if(NumOfParams%2==1)
1443 {
1444 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
1445 if(ok) val2=val2+1;
1446 };
1447 return QString::number(val2);
1448 };
1449 if (function=="COUNTIF")
1450 {
1451 //NumOfParams
1452 val1=functionCountIf(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function), getParameter(parameters, 2, TRUE, function));
1453 return QString::number(val1);
1454 };
1455 if (function=="MIN")
1456 {
1457 //NumOfParams
1458 val2=0.0;
1459 for(w1=1;w1<=(NumOfParams/2);w1++)
1460 {
1461 val1=functionMin(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
1462 val2=val1;
1463 };
1464 if(NumOfParams%2==1)
1465 {
1466 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
1467 if(val1<val2) val2=val1;
1468 };
1469 return QString::number(val2);
1470 };
1471 if (function=="MAX")
1472 {
1473 //NumOfParams
1474 val2=0.0;
1475 for(w1=1;w1<=(NumOfParams/2);w1++)
1476 {
1477 val1=functionMax(getParameter(parameters, (w1-1)*2, FALSE, function), getParameter(parameters, (w1-1)*2+1, TRUE, function));
1478 val2=val1;
1479 };
1480 if(NumOfParams%2==1)
1481 {
1482 val1=calculateVariable(getParameter(parameters,NumOfParams-1,FALSE, function)).toDouble(&ok);
1483 if(val1>val2) val2=val1;
1484 };
1485 return QString::number(val2);
1486 };
1487 if (function=="AVERAGE")
1488 {
1489 val1=functionAvg(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1490 return QString::number(val1);
1491 };
1492
1493 if(function=="BESSELI")
1494 {
1495 // BesselI (x,n)
1496 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1497 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1498 val2=BesselI(vali,val1);
1499 return QString::number(val2);
1500 };
1501 if(function=="BESSELJ")
1502 {
1503 // BesselJ (x,n)
1504 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1505 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1506 val2=BesselJ(vali,val1);
1507 return QString::number(val2);
1508 };
1509 if(function=="BESSELK")
1510 {
1511 // BesselK (x,n)
1512 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1513 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1514 val2=BesselK(vali,val1);
1515 return QString::number(val2);
1516 };
1517 if(function=="BESSELY")
1518 {
1519 // BesselY (x,n)
1520 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1521 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1522 val2=BesselY(vali,val1);
1523 return QString::number(val2);
1524 };
1525 if(function=="GAMMALN")
1526 {
1527 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1528 val2=GammaLn(val1);
1529 return QString::number(val2);
1530 };
1531 if(function=="ERF")
1532 {
1533 // ERF (a,b)
1534 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1535 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1536 return QString::number(ErrorFunction(val2)-ErrorFunction(val1));
1537 };
1538 if(function=="ERFC")
1539 {
1540 // ERFC (a,b)
1541 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1542 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1543 return QString::number(ErrorFunctionComplementary(val2)-ErrorFunctionComplementary(val1));
1544 };
1545 if(function=="POISSON")
1546 {
1547 // POISSON DISTR(x,n,distr/desnt)
1548 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1549 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1550 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
1551 if(vali==1)
1552 {
1553 return QString::number(GammaQ(floor(val1)+1, val2));
1554 }else
1555 {
1556 return QString::number(exp(-val2)*pow(val2,val1)/exp(GammaLn(val1+1.0)));
1557 };
1558 };
1559 if(function=="CHIDIST")
1560 {
1561 // POISSON CHIDIST(x,n,distr/density)
1562 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1563 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1564 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
1565 if(vali==1)
1566 {
1567 return QString::number(GammaP(val2/2.0,val1*val1/2.0));
1568 } else
1569 {
1570 return QString::number(
1571 pow(val1,val2-1.0)*exp(-val1*val1/2)/ ( pow(2,val2/2.0-1.0)*exp(GammaLn(val2/2.0)))
1572 );
1573 };
1574 };
1575 if(function=="CHI2DIST")
1576 {
1577 // POISSON CHISQUAREDIST(x,n,distr/density)
1578 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1579 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1580 vali=calculateVariable(getParameter(parameters, 2, TRUE, function)).toInt(&ok);
1581 if(vali==1)
1582 {
1583 return QString::number(GammaP(val2/2.0,val1/2.0));
1584 } else
1585 {
1586 return QString::number(
1587 pow(val1,val2/2.0-1.0)/(exp(val1/2.0)*pow(sqrt(2.0),val2)*exp(GammaLn(val2/2.0)))
1588 );
1589 };
1590 };
1591 if(function=="BETAI")
1592 {
1593 // BETA INCOMPLETE BETA(x,a,b)
1594 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1595 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1596 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
1597 return QString::number(BetaIncomplete(val2,val3,val1));
1598 };
1599 if(function=="GAMMAP")
1600 {
1601 // GammaP (x,a)
1602 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1603 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1604 return QString::number(GammaP(val2,val1));
1605 };
1606 if(function=="GAMMAQ")
1607 {
1608 // GammaQ (x,a)
1609 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1610 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1611 return QString::number(GammaQ(val2,val1));
1612 };
1613 if (function=="VAR")
1614 {
1615 val1=functionVariance(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1616 return QString::number(val1);
1617 };
1618 if (function=="VARP")
1619 {
1620 val1=functionVariancePopulation(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1621 return QString::number(val1);
1622 };
1623 if (function=="STDEV")
1624 {
1625 val1=functionVariance(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1626 if(val1<=0.0) return QString::number(0.0);
1627 return QString::number(sqrt(val1));
1628 };
1629 if (function=="STDEVP")
1630 {
1631 val1=functionVariancePopulation(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1632 if(val1<=0.0) return QString::number(0.0);
1633 return QString::number(sqrt(val1));
1634 };
1635 if (function=="SKEW")
1636 {
1637 val1=functionSkew(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1638 return QString::number(val1);
1639 };
1640 if (function=="KURT")
1641 {
1642 val1=functionKurt(getParameter(parameters, 0, TRUE, function), getParameter(parameters, 1, TRUE, function));
1643 return QString::number(val1);
1644 };
1645 if(function=="GAMMADIST")
1646 {
1647 // GAMMADIST (x,alpha,beta,distribution?density1:0)
1648 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1649 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1650 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
1651 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
1652 if(vali==1)//distribution
1653 {
1654 if(val3==0.0) return QString::number(0.0);
1655 else
1656 return QString::number(GammaP(val2,val1/val3));
1657 }else //density
1658 {
1659 return QString::number(
1660 pow(val1,val2-1.0)*exp(-val1/val3) / (pow(val3,val2)*exp(GammaLn(val2)))
1661 );
1662 };
1663 };
1664 if(function=="BETADIST")
1665 {
1666 // BETADIST (z,alpha,beta,distribution?density1:0)
1667 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1668 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1669 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
1670 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
1671 if(vali==1)//distribution
1672 {
1673 return QString::number(BetaIncomplete(val2,val3,val1));
1674 }else //density
1675 {
1676 return QString::number(
1677 pow(val1,val2-1.0)*pow(1.0-val1,val3-1.0) / Beta(val2,val3)
1678 );
1679 };
1680 };
1681 if(function=="FDIST")
1682 {
1683 // FDIST (z,d1,d2,distribution?density1:0)
1684 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1685 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1686 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
1687 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
1688 if(vali==1)//distribution
1689 {
1690 return QString::number(
1691 -BetaIncomplete(val3/2,val2/2,val3/(val3+val2*val1))
1692 +BetaIncomplete(val3/2,val2/2,1)
1693 );
1694 }else //density
1695 {
1696 return QString::number(
1697 pow(val2,val2/2)*pow(val3,val3/2)*pow(val1,val2/2-1)/
1698 (pow(val3+val2*val1,(val2+val3)/2)*Beta(val2/2,val3/2))
1699 );
1700 };
1701 };
1702 if(function=="NORMALDIST")
1703 {
1704 // NORMALDIST (x,m,s,distribution?density1:0)
1705 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1706 val2=calculateVariable(getParameter(parameters, 1, TRUE, function)).toDouble(&ok);
1707 val3=calculateVariable(getParameter(parameters, 2, TRUE, function)).toDouble(&ok);
1708 vali=calculateVariable(getParameter(parameters, 3, TRUE, function)).toInt(&ok);
1709 if(vali==1)//distribution
1710 {
1711 return QString::number(
1712 (ErrorFunction((val1-val2)/(sqrt(2)*val3))+1)/2.0
1713 );
1714 }else //density
1715 {
1716 return QString::number(
1717 exp(-pow(((val1-val2)/val3),2)/2)/(val3*sqrt(2*M_PI))
1718 );
1719 };
1720 };
1721 if(function=="PHI")
1722 {
1723 // NORMALDIST (x,distribution?density1:0) with mean=0 s=1.0
1724 val1=calculateVariable(getParameter(parameters, 0, TRUE, function)).toDouble(&ok);
1725 vali=calculateVariable(getParameter(parameters, 1, TRUE, function)).toInt(&ok);
1726 if(vali==1)//distribution
1727 {
1728 return QString::number(
1729 (ErrorFunction(val1/(sqrt(2)))+1)/2.0
1730 );
1731 }else //density
1732 {
1733 return QString::number(
1734 exp(-pow(val1,2)/2)/(sqrt(2*M_PI))
1735 );
1736 };
1737 };
1738 /*
1739 StudentTDistribution/: PDF[StudentTDistribution[n_], x_] :=
1740 1/(Sqrt[n] Beta[n/2, 1/2]) Sqrt[n/(n+x^2)]^(n+1) /;
1741 ParameterQ[StudentTDistribution[n]]
1742
1743 StudentTDistribution/: CDF[StudentTDistribution[n_], x_] :=
1744 (1 + Sign[x] BetaRegularized[n/(n+x^2), 1, n/2, 1/2])/2 /;
1745 ParameterQ[StudentTDistribution[n]]
1746 */
313 1747
314void Sheet::pushCharStack(QStack<QChar> *stackChars, const QChar &character)
315{
316 QChar *temp=new QChar(character);
317 stackChars->push(temp);
318}
319 1748
320void Sheet::pushStringStack(QStack<QString> *stackStrings, const QString &string)
321{
322 QString *temp=new QString(string);
323 stackStrings->push(temp);
324}
325 1749
326QChar Sheet::popCharStack(QStack<QChar> *stackChars) 1750 return 0;
327{ 1751};
328 if (stackChars->isEmpty())
329 {
330 QMessageBox::critical(this, tr("Error"), tr("Syntax error!"));
331 return '0';
332 }
333 1752
334 QChar *temp=stackChars->pop();
335 QChar temp2(*temp);
336 delete temp;
337 return temp2;
338}
339 1753
340QString Sheet::popStringStack(QStack<QString> *stackStrings)
341{
342 if (stackStrings->isEmpty())
343 {
344 QMessageBox::critical(this, tr("Error"), tr("Syntax error!"));
345 return "0";
346 }
347 1754
348 QString *temp=stackStrings->pop();
349 QString temp2(*temp);
350 delete temp;
351 return temp2;
352}
353 1755
354QString Sheet::dataParserHelper(const QString &data) 1756QString Sheet::dataParserHelper(const QString &data)
355{ 1757{
356 QStack<QString> stackElements; 1758 if(data.left(1)=="""" && data.right(1)=="""") return QString(data);
357 QStack<QChar> stackOperators; 1759 Expression exp1(data);
358 QString tempElement(""), temp2Element, firstElement, secondElement; 1760 exp1.Parse();
359 int paranCount; 1761 QStack<QString> stack1;
1762 stack1.setAutoDelete(TRUE);
1763 int i=0;
1764 QString* s1;
1765 QString* s2=NULL;
1766 int* i1;
1767 int args,tokentype;
1768 QString tempval;
1769 s1=exp1.CompiledBody.first();i1=exp1.CompiledBodyType.first();
1770 while(i<=(int)exp1.CompiledBody.count()-1)
1771 {
1772 args= ((*i1) & 0xFF00)>>8; tokentype=(*i1) & 0x00FF;
1773 if(tokentype==NUMBER_TOKEN)
1774 {
1775 stack1.push(new QString(*s1));
1776 //printf("Parse:Number=%s\r\n",s1->latin1());
1777 }
1778 else if(tokentype==VARIABLE_TOKEN)
1779 {
1780 stack1.push(new QString(*s1));
1781 //printf("Parse:Var=%s\r\n",s1->latin1());
1782 //here to put implementation of other types of variables except cell.
1783 //for example names
1784 }
1785 else if(tokentype==STRING_TOKEN)
1786 {
1787 stack1.push(new QString(*s1));
1788 //printf("Parse:String=%s\r\n",s1->ascii());
1789 }
1790 else if(tokentype==FUNCTION_TOKEN)
1791 {
1792 QString params="";
1793 for(int w1=1;w1<=args;w1++)
1794 {
1795 if((int)stack1.count()!=0) s2=stack1.pop();
1796 params=*s2+params;//args in reverse order
1797 params=","+params;
1798 };
1799 params=params.mid(1);
1800 if(params==NULL) params="0";
1801 //printf("Parse:Func=%s, params=%s, stackcount=%d,args=%d\r\n"
1802 //,s1->latin1(),params.latin1(),stack1.count(),args);
1803 tempval=calculateFunction(*s1,params,args);
1804 tempval=tempval.upper();
1805 stack1.push(new QString(tempval));
1806 };
1807
1808 //loops to next token
1809 if(exp1.CompiledBody.next()!=NULL) s1=exp1.CompiledBody.current(); else break;
1810 if(exp1.CompiledBodyType.next()!=NULL) i1=exp1.CompiledBodyType.current(); else break;
1811 i++;
1812 };
1813 if((int)stack1.count()!=0)s2=stack1.pop(); else s2=new QString("!ERROR");
1814 tempval=*s2;
1815 return(tempval);
1816};
360 1817
361 for (unsigned int i=0; i<data.length(); ++i)
362 {
363 if (data[i]=='+' || data[i]=='-' || data[i]=='*' || data[i]=='/')
364 {
365 pushStringStack(&stackElements, tempElement);
366 tempElement="";
367 if (!stackOperators.isEmpty() && getOperatorPriority(*stackOperators.top())>getOperatorPriority(data[i]))
368 {
369 secondElement=popStringStack(&stackElements);
370 firstElement=popStringStack(&stackElements);
371 pushStringStack(&stackElements, QString::number(calculateFunction(popCharStack(&stackOperators), firstElement+","+secondElement)));
372 }
373 pushCharStack(&stackOperators, data[i]);
374 }
375 else
376 if (data[i]==',')
377 {
378 if (!tempElement.isEmpty()) pushStringStack(&stackElements, tempElement);
379 while (!stackOperators.isEmpty())
380 {
381 secondElement=popStringStack(&stackElements);
382 firstElement=popStringStack(&stackElements);
383 pushStringStack(&stackElements, QString::number(calculateFunction(popCharStack(&stackOperators), firstElement+","+secondElement)));
384 }
385 tempElement="";
386 }
387 else
388 if (data[i]=='(')
389 {
390 paranCount=1;
391 temp2Element="";
392 for (++i; paranCount>0; ++i)
393 {
394 temp2Element+=data[i];
395 if (data[i]=='(') ++paranCount;
396 if (data[i]==')') --paranCount;
397 }
398 temp2Element=dataParserHelper(temp2Element.left(temp2Element.length()-1));
399 if (tempElement.isEmpty())
400 tempElement=temp2Element;
401 else
402 tempElement.setNum(calculateFunction(tempElement, temp2Element));
403 --i;
404 }
405 else
406 tempElement+=data[i];
407 }
408 if (!tempElement.isEmpty()) pushStringStack(&stackElements, tempElement);
409 while (!stackOperators.isEmpty())
410 {
411 secondElement=popStringStack(&stackElements);
412 firstElement=popStringStack(&stackElements);
413 pushStringStack(&stackElements, QString::number(calculateFunction(popCharStack(&stackOperators), firstElement+","+secondElement)));
414 }
415 1818
416 if (!stackElements.isEmpty())
417 tempElement=popStringStack(&stackElements);
418 while (!stackElements.isEmpty())
419 tempElement.prepend(popStringStack(&stackElements)+",");
420 return tempElement;
421}
422 1819
423QString Sheet::dataParser(const QString &cell, const QString &data) 1820QString Sheet::dataParser(const QString &cell, const QString &data)
424{ 1821{
425 QString strippedData(data); 1822 QString strippedData(data);
426 strippedData.replace(QRegExp("\\s"), ""); 1823 strippedData.replace(QRegExp("\\s"), "");
427 if (strippedData.isEmpty() || strippedData[0]!='=') return data; 1824 if (strippedData.isEmpty() || strippedData[0]!='=') return data;
428 if (listDataParser.find(cell)!=listDataParser.end()) return "0"; 1825 if (listDataParser.find(cell)!=listDataParser.end()) return "0";
429 listDataParser.append(cell); 1826 listDataParser.append(cell);
1827 // printf("DATAPARSER: data=%s, cell=%s\r\n",data.ascii(),cell.ascii());
430 strippedData=dataParserHelper(strippedData.remove(0, 1).upper().replace(QRegExp(":"), ",")); 1828 strippedData=dataParserHelper(strippedData.remove(0, 1).upper().replace(QRegExp(":"), ","));
431 1829
432 int i=0; 1830 int i=0;
433 QString tempParameter(getParameter(strippedData, i)), result=""; 1831 QString tempParameter(getParameter(strippedData, i)), result="";
434 do 1832 do
435 { 1833 {
436 result+=","+QString::number(calculateVariable(tempParameter)); 1834 result+=","+calculateVariable(tempParameter);
437 tempParameter=getParameter(strippedData, ++i); 1835 tempParameter=getParameter(strippedData, ++i);
438 } 1836 }
439 while (!tempParameter.isNull()); 1837 while (!tempParameter.isNull());
440 listDataParser.remove(cell); 1838 listDataParser.remove(cell);
441 return result.mid(1); 1839 return result.mid(1);
442} 1840}
443 1841
1842
444void Sheet::setData(const QString &data) 1843void Sheet::setData(const QString &data)
445{ 1844{
446 setText(currentRow(), currentColumn(), data); 1845 setText(currentRow(), currentColumn(), data);
447 slotCellChanged(currentRow(), currentColumn()); 1846 slotCellChanged(currentRow(), currentColumn());
448 activateNextCell(); 1847 activateNextCell();
449} 1848}
@@ -479,12 +1878,13 @@ void Sheet::paintCell(QPainter *p, int row, int col, const QRect & cr, bool sele
479 1878
480 QTableItem *cellItem=item(row, col); 1879 QTableItem *cellItem=item(row, col);
481 if (cellItem) 1880 if (cellItem)
482 { 1881 {
483 p->setPen(selected ? colorGroup().highlightedText() : cellData->fontColor); 1882 p->setPen(selected ? colorGroup().highlightedText() : cellData->fontColor);
484 p->setFont(cellData->font); 1883 p->setFont(cellData->font);
1884 QString str=cellItem->text();
485 p->drawText(2, 2, cr.width()-4, cr.height()-4, cellData->alignment, cellItem->text()); 1885 p->drawText(2, 2, cr.width()-4, cr.height()-4, cellData->alignment, cellItem->text());
486 } 1886 }
487 1887
488 int rx=cr.width()-1, ry=cr.height()-1; 1888 int rx=cr.width()-1, ry=cr.height()-1;
489 QPen pen(p->pen()); 1889 QPen pen(p->pen());
490 p->setPen(cellData->borders.right); 1890 p->setPen(cellData->borders.right);
@@ -867,6 +2267,299 @@ QString Sheet::getHeaderString(int section)
867 2267
868int Sheet::getHeaderColumn(const QString &section) 2268int Sheet::getHeaderColumn(const QString &section)
869{ 2269{
870 if (section.isEmpty()) return 0; 2270 if (section.isEmpty()) return 0;
871 return (section[section.length()-1]-'A'+1)+getHeaderColumn(section.left(section.length()-1))*26; 2271 return (section[section.length()-1]-'A'+1)+getHeaderColumn(section.left(section.length()-1))*26;
872} 2272}
2273
2274
2275//Expression Parser Class Definition
2276
2277
2278QChar Expression::chunk0(void)
2279{
2280 if(chunk.length()>0) return(chunk[0]); else return('\0');
2281};
2282
2283Expression::Expression(QString expr1)// constructor
2284{
2285 Body=expr1;
2286 SYMBOL="+-*/%^=()<>&|!,";
2287 MATHSYMBOL="+-*/%^=<>&|!,";
2288 // lnlim=1.0e-36; // Smallest number allowed
2289 // loglim=1.0e-10 ; // Smallest number allowed in call to log10() *
2290 ErrorFound=TRUE;
2291 n=0;chunk="";SymbGroup=NONE_TOKEN;InExpr=Body;
2292 ArgsOfFunc=0;
2293 CompiledBody.setAutoDelete(TRUE);
2294 CompiledBodyType.setAutoDelete(TRUE);
2295 //CompiledBody=QStringList(0);
2296};
2297
2298bool Expression::isSymbol(QChar ch)
2299{
2300 int j = 0;
2301 while (j<=((int)SYMBOL.length()-1) && ch!=SYMBOL[j]) j++;
2302 if(j<((int)SYMBOL.length())) return true; else return false;
2303};
2304
2305bool Expression::isMathSymbol(QChar ch)
2306{
2307 int j = 0;
2308 while (j<=((int)MATHSYMBOL.length()-1) && ch!=MATHSYMBOL[j]) j++;
2309 if(j<((int)MATHSYMBOL.length())) return true; else return false;
2310};
2311
2312void Expression::GetNext()
2313{
2314 chunk="";
2315 if(n>=(int)InExpr.length()) return;
2316 while (InExpr[n]==' ') n++;
2317 if(InExpr[n]=='\"')
2318 {
2319 while ( (n<(int)InExpr.length()) && (InExpr[n+1]!='\"') )
2320 {
2321 printf("chunk=%s\r\n",chunk.latin1());
2322 chunk+=InExpr[n];
2323 n++;
2324 };
2325 chunk+=InExpr[n];
2326 printf("2\r\n");
2327 SymbGroup=STRING_TOKEN;
2328 }
2329 else if (isSymbol(InExpr[n]))
2330 {
2331 SymbGroup=SYMBOL_TOKEN;
2332 chunk+=InExpr[n];
2333 n++;
2334 if( (n<(int)InExpr.length()) &&
2335 isMathSymbol(InExpr[n-1]) &&
2336 isMathSymbol(InExpr[n]) )
2337 {
2338 SymbGroup=SYMBOL_TOKEN;
2339 chunk+=InExpr[n];
2340 n++;
2341 };
2342 }
2343 else if ((InExpr[n].isLetter())||(InExpr[n]=='#'))
2344 {
2345 while ( (n<(int)InExpr.length()) && !isSymbol(InExpr[n]) )
2346 {
2347 if (!(InExpr[n]==' ')) chunk+=InExpr[n];
2348 n++;
2349 };
2350 if (InExpr[n]=='(') SymbGroup=FUNCTION_TOKEN; // function TOKEN
2351 else SymbGroup=VARIABLE_TOKEN;
2352 }
2353 else if((n<(int)InExpr.length()) &&
2354 ((InExpr[n].isDigit()) || (InExpr[n]=='.')))
2355 {
2356 while( n<(int)InExpr.length() )
2357 {
2358 if((InExpr[n].isDigit()) || InExpr[n]=='.')
2359 {
2360 chunk+=InExpr[n];
2361 SymbGroup=NUMBER_TOKEN;
2362 n++;
2363 }
2364 else if(InExpr[n]=='e')
2365 {
2366 if((n+1)<(int)InExpr.length())
2367 {
2368 if(InExpr[n+1]=='-' || InExpr[n+1]=='+' || InExpr[n+1].isDigit())
2369 {
2370 chunk+=InExpr[n];
2371 chunk+=InExpr[n+1];
2372 SymbGroup=NUMBER_TOKEN;
2373 n+=2;
2374 }
2375 }
2376 else
2377 {
2378 break;
2379 }
2380 }
2381 else
2382 {
2383 break;
2384 }
2385 }//while
2386 }//else if
2387};//end function
2388
2389
2390void Expression::First()
2391{
2392 GetNext();
2393 if (!(chunk=="") && !ErrorFound) Third();
2394 else ErrorFound = true;
2395};
2396
2397void Expression::Third()
2398{
2399 QChar sign, secS='\0';
2400 Fourth();
2401 sign = chunk0();
2402 if((int)chunk.length()>1) secS=chunk[1];
2403 while( sign == '+' || sign == '-'||
2404 sign == '<' || sign == '>'|| sign == '%'||
2405 sign == '&' || sign == '|' || sign == '!' || sign == '='
2406 )
2407 {
2408 GetNext();
2409 Fourth();
2410 QString name;
2411 if( sign == '+' ) name= "+" ;
2412 else if(sign=='-') name= "-" ;
2413 else if(sign=='>' && secS=='\0') name= ">" ;
2414 else if(sign=='<' && secS=='\0') name= "<" ;
2415 else if(sign=='=' && secS=='=') name= "==" ;
2416 else if(sign=='!' && secS=='=') name= "!=" ;
2417 else if(sign=='>' && secS=='=') name= ">=" ;
2418 else if(sign=='<' && secS=='=') name= "<=" ;
2419 else if(sign=='&' && secS=='&') name= "AND" ;
2420 else if(sign=='|' && secS=='|') name= "OR" ;
2421 else if(sign=='%') name= "MOD" ;
2422 CompiledBody.append(new QString(name)); // not sure if pushed in the back.
2423 CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8)); //2 argument functions
2424 sign = chunk0();
2425 }
2426};
2427
2428void Expression::Fourth()
2429{
2430 QChar sign;
2431 Fifth();
2432 sign = chunk0();
2433 while( sign == '*' || sign == '/' )
2434 {
2435 GetNext();
2436 Fifth();
2437 QString name;
2438 if( sign == '*' ) name= "*" ;
2439 else name= "/" ;
2440 CompiledBody.append(new QString(name));
2441 CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8)); //2 arguments functions
2442 sign = chunk0();
2443 }
2444};
2445
2446void Expression::Fifth()
2447{
2448 Sixth();
2449 //if(chunk.Length==0) return;
2450 if( chunk0() == '^' )
2451 {
2452 GetNext();
2453 Fifth();
2454 CompiledBody.append(new QString("POWER"));
2455 CompiledBodyType.append(new int(FUNCTION_TOKEN | 2<<8)); // 2 argument functions
2456 }
2457};
2458
2459void Expression::Sixth()
2460{
2461 char sign;
2462 sign = ' ';
2463 if(SymbGroup== SYMBOL_TOKEN &&
2464 chunk0() == '+' || chunk0() == '-' | chunk0() == '!')
2465 {
2466 sign = chunk0();
2467 GetNext();
2468 }
2469 Seventh();
2470 if( sign == '-' )
2471 {
2472 CompiledBody.append(new QString("CHGSGN")); // unary minus
2473 CompiledBodyType.append(new int(FUNCTION_TOKEN | 1<<8)); //1 argument
2474 }
2475 if( sign == '!' )
2476 {
2477 CompiledBody.append(new QString("NOT")); // unary minus
2478 CompiledBodyType.append(new int(FUNCTION_TOKEN | 1<<8)); //1 argument
2479 }
2480};
2481
2482
2483void Expression::Seventh()
2484{
2485 if( chunk0() == '(' && SymbGroup==SYMBOL_TOKEN)
2486 {
2487 GetNext();
2488 Third(); //parse the insides until we get a ')'
2489 if (chunk0() != ')') ErrorFound = true;
2490 GetNext();
2491 }
2492 else Eighth();
2493};
2494
2495void Expression::Eighth()
2496{
2497 if ( SymbGroup== NUMBER_TOKEN )
2498 {
2499 CompiledBody.append(new QString(chunk));
2500 CompiledBodyType.append(new int(NUMBER_TOKEN));
2501 GetNext();
2502 }
2503 else if ( SymbGroup== VARIABLE_TOKEN )
2504 {
2505 CompiledBody.append(new QString(chunk));
2506 CompiledBodyType.append(new int(VARIABLE_TOKEN));
2507 GetNext();
2508 }
2509 else if (SymbGroup== STRING_TOKEN )
2510 {
2511 CompiledBody.append(new QString(chunk+QString("\"")));
2512 CompiledBodyType.append(new int(STRING_TOKEN));
2513 GetNext();
2514 }
2515 else Ninth();
2516};
2517
2518void Expression::Ninth()
2519{
2520 if ( SymbGroup== FUNCTION_TOKEN )
2521 {
2522 QString TempFunk = chunk ;
2523 GetNext();
2524 if(chunk0() == '(' )
2525 {
2526 FuncDepth++;
2527 ArgsOfFunc.resize(FuncDepth+1);
2528 ArgsOfFunc[FuncDepth]=1;
2529 //ArgsOfFunc=1;
2530 GetNext();
2531 Third();
2532 while(chunk0()==',') //function arguments separator
2533 {
2534 //ArgsOfFunc++;
2535 ArgsOfFunc[FuncDepth]++;
2536 GetNext();
2537 Third();
2538 };
2539 if (chunk0() != ')') ErrorFound = true;
2540
2541 CompiledBody.append(new QString(TempFunk));
2542 if (TempFunk=="PI") ArgsOfFunc[FuncDepth]=0;
2543 // couldn't find a better way to parse function PI() with 0 args. :)
2544 CompiledBodyType.append(new int(FUNCTION_TOKEN | (ArgsOfFunc[FuncDepth]<<8) ));
2545 //the mask &FF00 gives the arguments of the functions passed.
2546 FuncDepth--;
2547 ArgsOfFunc.resize(FuncDepth+1);
2548 GetNext();
2549 }
2550 }
2551 else
2552 ErrorFound = true;
2553};
2554
2555bool Expression::Parse()
2556{
2557 CompiledBody.clear();
2558 ErrorFound = false;
2559 n = 0;ArgsOfFunc.resize(0);FuncDepth=0;
2560 InExpr=Body;
2561 First();
2562 return(!ErrorFound);
2563};
2564
2565