2000-09-18 23:16:46 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* $RCSfile: interpr3.cxx,v $
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2007-07-06 11:35:41 +00:00
|
|
|
* $Revision: 1.19 $
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2007-07-06 11:35:41 +00:00
|
|
|
* last change: $Author: rt $ $Date: 2007-07-06 12:35:41 $
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* The Contents of this file are made available subject to
|
|
|
|
* the terms of GNU Lesser General Public License Version 2.1.
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* GNU Lesser General Public License Version 2.1
|
|
|
|
* =============================================
|
|
|
|
* Copyright 2005 by Sun Microsystems, Inc.
|
|
|
|
* 901 San Antonio Road, Palo Alto, CA 94303, USA
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software Foundation.
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
2005-09-08 17:45:16 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
* MA 02111-1307 USA
|
2000-09-18 23:16:46 +00:00
|
|
|
*
|
|
|
|
************************************************************************/
|
|
|
|
|
2006-07-21 10:34:30 +00:00
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
|
|
#include "precompiled_sc.hxx"
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
// INCLUDE ---------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <tools/solar.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
2005-10-21 10:54:14 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <algorithm>
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
#include "interpre.hxx"
|
|
|
|
#include "global.hxx"
|
|
|
|
#include "compiler.hxx"
|
|
|
|
#include "cell.hxx"
|
|
|
|
#include "document.hxx"
|
|
|
|
#include "dociter.hxx"
|
|
|
|
#include "scmatrix.hxx"
|
|
|
|
#include "globstr.hrc"
|
|
|
|
|
|
|
|
// STATIC DATA -----------------------------------------------------------
|
|
|
|
|
|
|
|
#define SCdEpsilon 1.0E-7
|
|
|
|
#define SC_MAX_ITERATION_COUNT 20
|
|
|
|
#define MAX_ANZ_DOUBLE_FOR_SORT 100000
|
|
|
|
// PI jetzt als F_PI aus solar.h
|
|
|
|
//#define PI 3.1415926535897932
|
|
|
|
|
2001-01-05 17:26:27 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class ScDistFunc
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual double GetValue(double x) const = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// iteration for inverse distributions
|
|
|
|
|
|
|
|
//template< class T > double lcl_IterateInverse( const T& rFunction, double x0, double x1, BOOL& rConvError )
|
|
|
|
double lcl_IterateInverse( const ScDistFunc& rFunction, double x0, double x1, BOOL& rConvError )
|
|
|
|
{
|
|
|
|
rConvError = FALSE;
|
|
|
|
double fEps = 1.0E-7;
|
|
|
|
|
|
|
|
DBG_ASSERT(x0<x1, "IterateInverse: wrong interval");
|
|
|
|
|
|
|
|
// find enclosing interval
|
|
|
|
|
|
|
|
double f0 = rFunction.GetValue(x0);
|
|
|
|
double f1 = rFunction.GetValue(x1);
|
|
|
|
double xs;
|
|
|
|
USHORT i;
|
|
|
|
for (i = 0; i < 1000 && f0*f1 > 0.0; i++)
|
|
|
|
{
|
|
|
|
if (fabs(f0) <= fabs(f1))
|
|
|
|
{
|
|
|
|
xs = x0;
|
|
|
|
x0 += 2.0 * (x0 - x1);
|
|
|
|
if (x0 < 0.0)
|
|
|
|
x0 = 0.0;
|
|
|
|
x1 = xs;
|
|
|
|
f1 = f0;
|
|
|
|
f0 = rFunction.GetValue(x0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xs = x1;
|
|
|
|
x1 += 2.0 * (x1 - x0);
|
|
|
|
x0 = xs;
|
|
|
|
f0 = f1;
|
|
|
|
f1 = rFunction.GetValue(x1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f0 == 0.0)
|
|
|
|
return x0;
|
|
|
|
if (f1 == 0.0)
|
|
|
|
return x1;
|
|
|
|
|
|
|
|
// simple iteration
|
|
|
|
|
|
|
|
double x00 = x0;
|
|
|
|
double x11 = x1;
|
2007-02-27 11:16:29 +00:00
|
|
|
double fs = 0.0;
|
2001-01-05 17:26:27 +00:00
|
|
|
for (i = 0; i < 100; i++)
|
|
|
|
{
|
|
|
|
xs = 0.5*(x0+x1);
|
|
|
|
if (fabs(f1-f0) >= fEps)
|
|
|
|
{
|
|
|
|
fs = rFunction.GetValue(xs);
|
|
|
|
if (f0*fs <= 0.0)
|
|
|
|
{
|
|
|
|
x1 = xs;
|
|
|
|
f1 = fs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x0 = xs;
|
|
|
|
f0 = fs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// add one step of regula falsi to improve precision
|
|
|
|
|
|
|
|
if ( x0 != x1 )
|
|
|
|
{
|
|
|
|
double regxs = (f1-f0)/(x1-x0);
|
|
|
|
if ( regxs != 0.0)
|
|
|
|
{
|
|
|
|
double regx = x1 - f1/regxs;
|
|
|
|
if (regx >= x00 && regx <= x11)
|
|
|
|
{
|
|
|
|
double regfs = rFunction.GetValue(regx);
|
|
|
|
if ( fabs(regfs) < fabs(fs) )
|
|
|
|
xs = regx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return xs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rConvError = TRUE;
|
|
|
|
return 0.0;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Allgemeine Funktionen
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void ScInterpreter::ScNoName()
|
|
|
|
{
|
|
|
|
SetError(errNoName);
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::phi(double x)
|
|
|
|
{
|
|
|
|
return 0.39894228040143268 * exp(-(x * x) / 2.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::taylor(double* pPolynom, USHORT nMax, double x)
|
|
|
|
{
|
|
|
|
double nVal = pPolynom[nMax];
|
|
|
|
for (short i = nMax-1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
nVal = pPolynom[i] + (nVal * x);
|
|
|
|
}
|
|
|
|
return nVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::gauss(double x)
|
|
|
|
{
|
|
|
|
double t0[] =
|
|
|
|
{ 0.39894228040143268, -0.06649038006690545, 0.00997355701003582,
|
|
|
|
-0.00118732821548045, 0.00011543468761616, -0.00000944465625950,
|
|
|
|
0.00000066596935163, -0.00000004122667415, 0.00000000227352982,
|
|
|
|
0.00000000011301172, 0.00000000000511243, -0.00000000000021218 };
|
|
|
|
double t2[] =
|
|
|
|
{ 0.47724986805182079, 0.05399096651318805, -0.05399096651318805,
|
|
|
|
0.02699548325659403, -0.00449924720943234, -0.00224962360471617,
|
|
|
|
0.00134977416282970, -0.00011783742691370, -0.00011515930357476,
|
|
|
|
0.00003704737285544, 0.00000282690796889, -0.00000354513195524,
|
|
|
|
0.00000037669563126, 0.00000019202407921, -0.00000005226908590,
|
|
|
|
-0.00000000491799345, 0.00000000366377919, -0.00000000015981997,
|
|
|
|
-0.00000000017381238, 0.00000000002624031, 0.00000000000560919,
|
|
|
|
-0.00000000000172127, -0.00000000000008634, 0.00000000000007894 };
|
|
|
|
double t4[] =
|
|
|
|
{ 0.49996832875816688, 0.00013383022576489, -0.00026766045152977,
|
|
|
|
0.00033457556441221, -0.00028996548915725, 0.00018178605666397,
|
|
|
|
-0.00008252863922168, 0.00002551802519049, -0.00000391665839292,
|
|
|
|
-0.00000074018205222, 0.00000064422023359, -0.00000017370155340,
|
|
|
|
0.00000000909595465, 0.00000000944943118, -0.00000000329957075,
|
|
|
|
0.00000000029492075, 0.00000000011874477, -0.00000000004420396,
|
|
|
|
0.00000000000361422, 0.00000000000143638, -0.00000000000045848 };
|
|
|
|
double asympt[] = { -1.0, 1.0, -3.0, 15.0, -105.0 };
|
|
|
|
|
|
|
|
double xAbs = fabs(x);
|
2003-03-26 17:07:02 +00:00
|
|
|
USHORT xShort = (USHORT)::rtl::math::approxFloor(xAbs);
|
2000-09-18 23:16:46 +00:00
|
|
|
double nVal = 0.0;
|
|
|
|
if (xShort == 0)
|
|
|
|
nVal = taylor(t0, 11, (xAbs * xAbs)) * xAbs;
|
|
|
|
else if ((xShort >= 1) && (xShort <= 2))
|
|
|
|
nVal = taylor(t2, 23, (xAbs - 2.0));
|
|
|
|
else if ((xShort >= 3) && (xShort <= 4))
|
|
|
|
nVal = taylor(t4, 20, (xAbs - 4.0));
|
|
|
|
else
|
|
|
|
nVal = 0.5 + phi(xAbs) * taylor(asympt, 4, 1.0 / (xAbs * xAbs)) / xAbs;
|
|
|
|
if (x < 0.0)
|
|
|
|
return -nVal;
|
|
|
|
else
|
|
|
|
return nVal;
|
|
|
|
}
|
|
|
|
|
2005-10-25 09:59:48 +00:00
|
|
|
//
|
|
|
|
// #i26836# new gaussinv implementation by Martin Eitzenberger <m.eitzenberger@unix.net>
|
|
|
|
//
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
double ScInterpreter::gaussinv(double x)
|
|
|
|
{
|
2005-10-25 09:59:48 +00:00
|
|
|
double q,t,z;
|
|
|
|
|
|
|
|
q=x-0.5;
|
|
|
|
|
|
|
|
if(fabs(q)<=.425)
|
|
|
|
{
|
|
|
|
t=0.180625-q*q;
|
|
|
|
|
|
|
|
z=
|
|
|
|
q*
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
t*2509.0809287301226727+33430.575583588128105
|
|
|
|
)
|
|
|
|
*t+67265.770927008700853
|
|
|
|
)
|
|
|
|
*t+45921.953931549871457
|
|
|
|
)
|
|
|
|
*t+13731.693765509461125
|
|
|
|
)
|
|
|
|
*t+1971.5909503065514427
|
|
|
|
)
|
|
|
|
*t+133.14166789178437745
|
|
|
|
)
|
|
|
|
*t+3.387132872796366608
|
|
|
|
)
|
|
|
|
/
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
t*5226.495278852854561+28729.085735721942674
|
|
|
|
)
|
|
|
|
*t+39307.89580009271061
|
|
|
|
)
|
|
|
|
*t+21213.794301586595867
|
|
|
|
)
|
|
|
|
*t+5394.1960214247511077
|
|
|
|
)
|
|
|
|
*t+687.1870074920579083
|
|
|
|
)
|
|
|
|
*t+42.313330701600911252
|
|
|
|
)
|
|
|
|
*t+1.0
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
2005-10-25 09:59:48 +00:00
|
|
|
{
|
|
|
|
if(q>0) t=1-x;
|
|
|
|
else t=x;
|
|
|
|
|
|
|
|
t=sqrt(-log(t));
|
|
|
|
|
|
|
|
if(t<=5.0)
|
|
|
|
{
|
|
|
|
t+=-1.6;
|
|
|
|
|
|
|
|
z=
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
t*7.7454501427834140764e-4+0.0227238449892691845833
|
|
|
|
)
|
|
|
|
*t+0.24178072517745061177
|
|
|
|
)
|
|
|
|
*t+1.27045825245236838258
|
|
|
|
)
|
|
|
|
*t+3.64784832476320460504
|
|
|
|
)
|
|
|
|
*t+5.7694972214606914055
|
|
|
|
)
|
|
|
|
*t+4.6303378461565452959
|
|
|
|
)
|
|
|
|
*t+1.42343711074968357734
|
|
|
|
)
|
|
|
|
/
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
t*1.05075007164441684324e-9+5.475938084995344946e-4
|
|
|
|
)
|
|
|
|
*t+0.0151986665636164571966
|
|
|
|
)
|
|
|
|
*t+0.14810397642748007459
|
|
|
|
)
|
|
|
|
*t+0.68976733498510000455
|
|
|
|
)
|
|
|
|
*t+1.6763848301838038494
|
|
|
|
)
|
|
|
|
*t+2.05319162663775882187
|
|
|
|
)
|
|
|
|
*t+1.0
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
t+=-5.0;
|
|
|
|
|
|
|
|
z=
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
t*2.01033439929228813265e-7+2.71155556874348757815e-5
|
|
|
|
)
|
|
|
|
*t+0.0012426609473880784386
|
|
|
|
)
|
|
|
|
*t+0.026532189526576123093
|
|
|
|
)
|
|
|
|
*t+0.29656057182850489123
|
|
|
|
)
|
|
|
|
*t+1.7848265399172913358
|
|
|
|
)
|
|
|
|
*t+5.4637849111641143699
|
|
|
|
)
|
|
|
|
*t+6.6579046435011037772
|
|
|
|
)
|
|
|
|
/
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
(
|
|
|
|
t*2.04426310338993978564e-15+1.4215117583164458887e-7
|
|
|
|
)
|
|
|
|
*t+1.8463183175100546818e-5
|
|
|
|
)
|
|
|
|
*t+7.868691311456132591e-4
|
|
|
|
)
|
|
|
|
*t+0.0148753612908506148525
|
|
|
|
)
|
|
|
|
*t+0.13692988092273580531
|
|
|
|
)
|
|
|
|
*t+0.59983220655588793769
|
|
|
|
)
|
|
|
|
*t+1.0
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(q<0.0) z=-z;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::Fakultaet(double x)
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
x = ::rtl::math::approxFloor(x);
|
2000-09-18 23:16:46 +00:00
|
|
|
if (x < 0.0)
|
|
|
|
return 0.0;
|
|
|
|
else if (x == 0.0)
|
|
|
|
return 1.0;
|
|
|
|
else if (x <= 170.0)
|
|
|
|
{
|
|
|
|
double fTemp = x;
|
|
|
|
while (fTemp > 2.0)
|
|
|
|
{
|
|
|
|
fTemp--;
|
|
|
|
x *= fTemp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SetError(errNoValue);
|
|
|
|
/* // Stirlingsche Naeherung zu ungenau
|
|
|
|
else
|
|
|
|
x = pow(x/exp(1), x) * sqrt(x) * SQRT_2_PI * (1.0 + 1.0 / (12.0 * x));
|
|
|
|
*/
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::BinomKoeff(double n, double k)
|
|
|
|
{
|
|
|
|
double nVal = 0.0;
|
2003-03-26 17:07:02 +00:00
|
|
|
k = ::rtl::math::approxFloor(k);
|
2000-09-18 23:16:46 +00:00
|
|
|
if (n < k)
|
|
|
|
nVal = 0.0;
|
|
|
|
else if (k == 0.0)
|
|
|
|
nVal = 1.0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nVal = n/k;
|
|
|
|
n--;
|
|
|
|
k--;
|
|
|
|
while (k > 0.0)
|
|
|
|
{
|
|
|
|
nVal *= n/k;
|
|
|
|
k--;
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
double f1 = n; // Zaehler
|
|
|
|
double f2 = k; // Nenner
|
|
|
|
n--;
|
|
|
|
k--;
|
|
|
|
while (k > 0.0)
|
|
|
|
{
|
|
|
|
f2 *= k;
|
|
|
|
f1 *= n;
|
|
|
|
k--;
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
nVal = f1 / f2;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
return nVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GammaHelp(double& x, BOOL& bReflect)
|
|
|
|
{
|
|
|
|
double c[6] = {76.18009173, -86.50532033, 24.01409822,
|
|
|
|
-1.231739516, 0.120858003E-2, -0.536382E-5};
|
|
|
|
if (x >= 1.0)
|
|
|
|
{
|
|
|
|
bReflect = FALSE;
|
|
|
|
x -= 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bReflect = TRUE;
|
|
|
|
x = 1.0 - x;
|
|
|
|
}
|
|
|
|
double s, anum;
|
|
|
|
s = 1.0;
|
|
|
|
anum = x;
|
|
|
|
for (USHORT i = 0; i < 6; i++)
|
|
|
|
{
|
|
|
|
anum += 1.0;
|
|
|
|
s += c[i]/anum;
|
|
|
|
}
|
|
|
|
s *= 2.506628275; // sqrt(2*PI)
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GetGamma(double x)
|
|
|
|
{
|
|
|
|
BOOL bReflect;
|
|
|
|
double G = GammaHelp(x, bReflect);
|
|
|
|
G = pow(x+5.5,x+0.5)*G/exp(x+5.5);
|
|
|
|
if (bReflect)
|
2003-03-26 17:07:02 +00:00
|
|
|
G = F_PI*x/(G*::rtl::math::sin(F_PI*x));
|
2000-09-18 23:16:46 +00:00
|
|
|
return G;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GetLogGamma(double x)
|
|
|
|
{
|
|
|
|
BOOL bReflect;
|
|
|
|
double G = GammaHelp(x, bReflect);
|
|
|
|
G = (x+0.5)*log(x+5.5)+log(G)-(x+5.5);
|
|
|
|
if (bReflect)
|
2003-03-26 17:07:02 +00:00
|
|
|
G = log(F_PI*x)-G-log(::rtl::math::sin(F_PI*x));
|
2000-09-18 23:16:46 +00:00
|
|
|
return G;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GetBetaDist(double x, double alpha, double beta)
|
|
|
|
{
|
|
|
|
if (beta == 1.0)
|
|
|
|
return pow(x, alpha);
|
|
|
|
else if (alpha == 1.0)
|
|
|
|
return 1.0 - pow(1.0-x,beta);
|
|
|
|
double fEps = 1.0E-8;
|
|
|
|
BOOL bReflect;
|
|
|
|
double cf, fA, fB;
|
|
|
|
if (x < (alpha+1.0)/(alpha+beta+1.0))
|
|
|
|
{
|
|
|
|
bReflect = FALSE;
|
|
|
|
fA = alpha;
|
|
|
|
fB = beta;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bReflect = TRUE;
|
|
|
|
fA = beta;
|
|
|
|
fB = alpha;
|
|
|
|
x = 1.0 - x;
|
|
|
|
}
|
|
|
|
if (x < fEps)
|
|
|
|
cf = 0.0;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double a1, b1, a2, b2, fnorm, rm, apl2m, d2m, d2m1, cfnew;
|
|
|
|
a1 = 1.0; b1 = 1.0;
|
|
|
|
b2 = 1.0 - (fA+fB)*x/(fA+1.0);
|
|
|
|
if (b2 == 0.0)
|
|
|
|
{
|
|
|
|
a2 = b2;
|
|
|
|
fnorm = 1.0;
|
|
|
|
cf = 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a2 = 1.0;
|
|
|
|
fnorm = 1.0/b2;
|
|
|
|
cf = a2*fnorm;
|
|
|
|
}
|
|
|
|
cfnew = 1.0;
|
|
|
|
for (USHORT j = 1; j <= 100; j++)
|
|
|
|
{
|
|
|
|
rm = (double) j;
|
|
|
|
apl2m = fA + 2.0*rm;
|
|
|
|
d2m = rm*(fB-rm)*x/((apl2m-1.0)*apl2m);
|
|
|
|
d2m1 = -(fA+rm)*(fA+fB+rm)*x/(apl2m*(apl2m+1.0));
|
|
|
|
a1 = (a2+d2m*a1)*fnorm;
|
|
|
|
b1 = (b2+d2m*b1)*fnorm;
|
|
|
|
a2 = a1 + d2m1*a2*fnorm;
|
|
|
|
b2 = b1 + d2m1*b2*fnorm;
|
|
|
|
if (b2 != 0.0)
|
|
|
|
{
|
|
|
|
fnorm = 1.0/b2;
|
|
|
|
cfnew = a2*fnorm;
|
|
|
|
if (fabs(cf-cfnew)/cf < fEps)
|
|
|
|
j = 101;
|
|
|
|
else
|
|
|
|
cf = cfnew;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fB < fEps)
|
2003-05-13 11:33:04 +00:00
|
|
|
b1 = 69; // ln(1.0E30)
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
2003-05-13 11:33:04 +00:00
|
|
|
b1 = GetLogGamma(fA)+GetLogGamma(fB)-GetLogGamma(fA+fB);
|
2000-09-18 23:16:46 +00:00
|
|
|
|
2003-05-13 11:33:04 +00:00
|
|
|
// cf *= pow(x, fA)*pow(1.0-x,fB)/(fA*exp(b1));
|
|
|
|
// #108995# The formula above has 0 as results for the terms too easily,
|
|
|
|
// resulting in an error where the equivalent formula below still works:
|
|
|
|
// (x can't be 0 or 1, this is handled above)
|
|
|
|
cf *= exp( log(x)*fA + log(1.0-x)*fB - b1 ) / fA;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
if (bReflect)
|
|
|
|
return 1.0-cf;
|
|
|
|
else
|
|
|
|
return cf;
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GetFDist(double x, double fF1, double fF2)
|
|
|
|
{
|
|
|
|
double arg = fF2/(fF2+fF1*x);
|
|
|
|
double alpha = fF2/2.0;
|
|
|
|
double beta = fF1/2.0;
|
|
|
|
return (GetBetaDist(arg, alpha, beta));
|
|
|
|
/*
|
|
|
|
double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
|
|
|
|
sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
|
|
|
|
return (0.5-gauss(Z));
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GetTDist(double T, double fDF)
|
|
|
|
{
|
|
|
|
return 0.5 * GetBetaDist(fDF/(fDF+T*T), fDF/2.0, 0.5);
|
|
|
|
/*
|
|
|
|
USHORT DF = (USHORT) fDF;
|
|
|
|
double A = T / sqrt(DF);
|
|
|
|
double B = 1.0 + A*A;
|
|
|
|
double R;
|
|
|
|
if (DF == 1)
|
|
|
|
R = 0.5 + atan(A)/F_PI;
|
|
|
|
else if (DF % 2 == 0)
|
|
|
|
{
|
|
|
|
double S0 = A/(2.0 * sqrt(B));
|
|
|
|
double C0 = S0;
|
|
|
|
for (USHORT i = 2; i <= DF-2; i+=2)
|
|
|
|
{
|
|
|
|
C0 *= (1.0 - 1.0/(double)i)/B;
|
|
|
|
S0 += C0;
|
|
|
|
}
|
|
|
|
R = 0.5 + S0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double S1 = A / (B * F_PI);
|
|
|
|
double C1 = S1;
|
|
|
|
for (USHORT i = 3; i <= DF-2; i+=2)
|
|
|
|
{
|
|
|
|
C1 *= (1.0 - 1.0/(double)i)/B;
|
|
|
|
S1 += C1;
|
|
|
|
}
|
|
|
|
R = 0.5 + atan(A)/F_PI + S1;
|
|
|
|
}
|
|
|
|
return 1.0 - R;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
double ScInterpreter::GetChiDist(double fChi, double fDF)
|
|
|
|
{
|
|
|
|
return 1.0 - GetGammaDist(fChi/2.0, fDF/2.0, 1.0);
|
|
|
|
/*
|
|
|
|
double x = 1.0;
|
|
|
|
for (double i = fDF; i >= 2.0; i -= 2.0)
|
|
|
|
x *= fChi/i;
|
|
|
|
x *= exp(-fChi/2.0);
|
|
|
|
if (fmod(fDF, 2.0) != 0.0)
|
|
|
|
x *= sqrt(2.0*fChi/F_PI);
|
|
|
|
double S = 1.0;
|
|
|
|
double T = 1.0;
|
|
|
|
double G = fDF;
|
|
|
|
BOOL bStop = FALSE;
|
|
|
|
while (!bStop)
|
|
|
|
{
|
|
|
|
G += 2.0;
|
|
|
|
T *= fChi/G;
|
|
|
|
if (T < 1.0E-7)
|
|
|
|
bStop = TRUE;
|
|
|
|
else
|
|
|
|
S += T;
|
|
|
|
}
|
|
|
|
return 1.0 - x*S;
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScLogGamma()
|
|
|
|
{
|
|
|
|
double x = GetDouble();
|
|
|
|
if (x > 0.0)
|
|
|
|
PushDouble(GetLogGamma(x));
|
|
|
|
else
|
|
|
|
SetIllegalArgument();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScBetaDist()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
|
|
|
|
return;
|
|
|
|
double fA, fB, alpha, beta, x;
|
|
|
|
if (nParamCount == 5)
|
|
|
|
fB = GetDouble();
|
|
|
|
else
|
|
|
|
fB = 1.0;
|
|
|
|
if (nParamCount >= 4)
|
|
|
|
fA = GetDouble();
|
|
|
|
else
|
|
|
|
fA = 0.0;
|
|
|
|
beta = GetDouble();
|
|
|
|
alpha = GetDouble();
|
|
|
|
x = GetDouble();
|
|
|
|
if (x < fA || x > fB || fA == fB || alpha <= 0.0 || beta <= 0.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
x = (x-fA)/(fB-fA); // Skalierung auf (0,1)
|
|
|
|
PushDouble(GetBetaDist(x, alpha, beta));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScPhi()
|
|
|
|
{
|
|
|
|
PushDouble(phi(GetDouble()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScGauss()
|
|
|
|
{
|
|
|
|
PushDouble(gauss(GetDouble()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScFisher()
|
|
|
|
{
|
|
|
|
double fVal = GetDouble();
|
|
|
|
if (fabs(fVal) >= 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(0.5*log((1.0+fVal)/(1.0-fVal)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScFisherInv()
|
|
|
|
{
|
|
|
|
double fVal = GetDouble();
|
|
|
|
PushDouble((exp(2.0*fVal)-1.0)/(exp(2.0*fVal)+1.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScFact()
|
|
|
|
{
|
|
|
|
double nVal = GetDouble();
|
|
|
|
if (nVal < 0.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(Fakultaet(nVal));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScKombin()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
double k = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (k < 0.0 || n < 0.0 || k > n)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(BinomKoeff(n, k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScKombin2()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
double k = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (k < 0.0 || n < 0.0 || k > n)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(BinomKoeff(n + k - 1, k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScVariationen()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
double k = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (n < 0.0 || k < 0.0 || k > n)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (k == 0.0)
|
|
|
|
PushInt(1); // (n! / (n - 0)!) == 1
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double nVal = n;
|
|
|
|
for (ULONG i = (ULONG)k-1; i >= 1; i--)
|
|
|
|
nVal *= n-(double)i;
|
|
|
|
PushDouble(nVal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScVariationen2()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
double k = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (n < 0.0 || k < 0.0 || k > n)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(pow(n,k));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScB()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
|
|
|
|
return ;
|
|
|
|
if (nParamCount == 3)
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
double x = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double p = GetDouble();
|
2003-03-26 17:07:02 +00:00
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double q = 1.0 - p;
|
|
|
|
double fFactor = pow(q, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
{
|
|
|
|
fFactor = pow(p, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG max = (ULONG) (n - x);
|
|
|
|
for (ULONG i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
fFactor *= (n-i)/(i+1)*q/p;
|
|
|
|
PushDouble(fFactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG max = (ULONG) x;
|
|
|
|
for (ULONG i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
fFactor *= (n-i)/(i+1)*p/q;
|
|
|
|
PushDouble(fFactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (nParamCount == 4)
|
|
|
|
{
|
|
|
|
double xe = GetDouble();
|
|
|
|
double xs = GetDouble();
|
|
|
|
double p = GetDouble();
|
|
|
|
double n = GetDouble();
|
|
|
|
// alter Stand 300-SC
|
|
|
|
// if ((xs < n) && (xe < n) && (p < 1.0))
|
|
|
|
// {
|
|
|
|
// double Varianz = sqrt(n * p * (1.0 - p));
|
|
|
|
// xs = fabs(xs - (n * p /* / 2.0 STE */ ));
|
|
|
|
// xe = fabs(xe - (n * p /* / 2.0 STE */ ));
|
|
|
|
//// STE double nVal = gauss((xs + 0.5) / Varianz) + gauss((xe + 0.5) / Varianz);
|
|
|
|
// double nVal = fabs(gauss(xs / Varianz) - gauss(xe / Varianz));
|
|
|
|
// PushDouble(nVal);
|
|
|
|
// }
|
|
|
|
if (xe <= n && xs <= xe &&
|
|
|
|
p < 1.0 && p > 0.0 && n >= 0.0 && xs >= 0.0 )
|
|
|
|
{
|
|
|
|
double q = 1.0 - p;
|
|
|
|
double fFactor = pow(q, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
{
|
|
|
|
fFactor = pow(p, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double fSum = 0.0;
|
|
|
|
ULONG max;
|
|
|
|
if (xe < (ULONG) n)
|
|
|
|
max = (ULONG) (n-xe)-1;
|
|
|
|
else
|
|
|
|
max = 0;
|
|
|
|
ULONG i;
|
|
|
|
for (i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
fFactor *= (n-i)/(i+1)*q/p;
|
|
|
|
if (xs < (ULONG) n)
|
|
|
|
max = (ULONG) (n-xs);
|
|
|
|
else
|
|
|
|
fSum = fFactor;
|
|
|
|
for (; i < max && fFactor > 0.0; i++)
|
|
|
|
{
|
|
|
|
fFactor *= (n-i)/(i+1)*q/p;
|
|
|
|
fSum += fFactor;
|
|
|
|
}
|
|
|
|
PushDouble(fSum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG max;
|
|
|
|
double fSum;
|
|
|
|
if ( (ULONG) xs == 0)
|
|
|
|
{
|
|
|
|
fSum = fFactor;
|
|
|
|
max = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
max = (ULONG) xs-1;
|
|
|
|
fSum = 0.0;
|
|
|
|
}
|
|
|
|
ULONG i;
|
|
|
|
for (i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
fFactor *= (n-i)/(i+1)*p/q;
|
|
|
|
if ((ULONG)xe == 0) // beide 0
|
|
|
|
fSum = fFactor;
|
|
|
|
else
|
|
|
|
max = (ULONG) xe;
|
|
|
|
for (; i < max && fFactor > 0.0; i++)
|
|
|
|
{
|
|
|
|
fFactor *= (n-i)/(i+1)*p/q;
|
|
|
|
fSum += fFactor;
|
|
|
|
}
|
|
|
|
PushDouble(fSum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SetIllegalArgument();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScBinomDist()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 4 ) )
|
|
|
|
{
|
|
|
|
double kum = GetDouble(); // 0 oder 1
|
|
|
|
double p = GetDouble(); // p
|
2003-03-26 17:07:02 +00:00
|
|
|
double n = ::rtl::math::approxFloor(GetDouble()); // n
|
|
|
|
double x = ::rtl::math::approxFloor(GetDouble()); // x
|
2000-09-18 23:16:46 +00:00
|
|
|
double fFactor, q, fSum;
|
|
|
|
if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (kum == 0.0) // Dichte
|
|
|
|
{
|
|
|
|
q = 1.0 - p;
|
|
|
|
fFactor = pow(q, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
{
|
|
|
|
fFactor = pow(p, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG max = (ULONG) (n - x);
|
|
|
|
for (ULONG i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
fFactor *= (n-i)/(i+1)*q/p;
|
|
|
|
PushDouble(fFactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ULONG max = (ULONG) x;
|
|
|
|
for (ULONG i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
fFactor *= (n-i)/(i+1)*p/q;
|
|
|
|
PushDouble(fFactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // Verteilung
|
|
|
|
{
|
|
|
|
if (n == x)
|
|
|
|
PushDouble(1.0);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
q = 1.0 - p;
|
|
|
|
fFactor = pow(q, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
{
|
|
|
|
fFactor = pow(p, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fSum = 1.0 - fFactor;
|
|
|
|
ULONG max = (ULONG) (n - x) - 1;
|
|
|
|
for (ULONG i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
{
|
|
|
|
fFactor *= (n-i)/(i+1)*q/p;
|
|
|
|
fSum -= fFactor;
|
|
|
|
}
|
|
|
|
if (fSum < 0.0)
|
|
|
|
PushDouble(0.0);
|
|
|
|
else
|
|
|
|
PushDouble(fSum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
fSum = fFactor;
|
2000-09-18 23:16:46 +00:00
|
|
|
ULONG max = (ULONG) x;
|
|
|
|
for (ULONG i = 0; i < max && fFactor > 0.0; i++)
|
|
|
|
{
|
|
|
|
fFactor *= (n-i)/(i+1)*p/q;
|
|
|
|
fSum += fFactor;
|
|
|
|
}
|
|
|
|
PushDouble(fSum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScCritBinom()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double alpha = GetDouble(); // alpha
|
|
|
|
double p = GetDouble(); // p
|
2003-03-26 17:07:02 +00:00
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (n < 0.0 || alpha <= 0.0 || alpha >= 1.0 || p < 0.0 || p > 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double q = 1.0 - p;
|
|
|
|
double fFactor = pow(q,n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
{
|
|
|
|
fFactor = pow(p, n);
|
|
|
|
if (fFactor == 0.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double fSum = 1.0 - fFactor; ULONG max = (ULONG) n;
|
2003-12-01 16:51:14 +00:00
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for ( i = 0; i < max && fSum >= alpha; i++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
fFactor *= (n-i)/(i+1)*q/p;
|
|
|
|
fSum -= fFactor;
|
|
|
|
}
|
|
|
|
PushDouble(n-i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double fSum = fFactor; ULONG max = (ULONG) n;
|
2003-12-01 16:51:14 +00:00
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
for ( i = 0; i < max && fSum < alpha; i++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
fFactor *= (n-i)/(i+1)*p/q;
|
|
|
|
fSum += fFactor;
|
|
|
|
}
|
|
|
|
PushDouble(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScNegBinomDist()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double p = GetDouble(); // p
|
|
|
|
double r = GetDouble(); // r
|
|
|
|
double x = GetDouble(); // x
|
|
|
|
if (r < 0.0 || x < 0.0 || p < 0.0 || p > 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double q = 1.0 - p;
|
|
|
|
double fFactor = pow(p,r);
|
|
|
|
for (double i = 0.0; i < x; i++)
|
|
|
|
fFactor *= (i+r)/(i+1.0)*q;
|
|
|
|
PushDouble(fFactor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScNormDist()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 4 ) )
|
|
|
|
{
|
|
|
|
double kum = GetDouble(); // 0 oder 1
|
|
|
|
double sigma = GetDouble(); // Stdabw
|
|
|
|
double mue = GetDouble(); // Mittelwert
|
|
|
|
double x = GetDouble(); // x
|
2007-07-06 11:35:41 +00:00
|
|
|
if (sigma < 0.0)
|
|
|
|
PushError( errIllegalArgument);
|
|
|
|
else if (sigma == 0.0)
|
|
|
|
PushError( errDivisionByZero);
|
2000-09-18 23:16:46 +00:00
|
|
|
else if (kum == 0.0) // Dichte
|
|
|
|
PushDouble(phi((x-mue)/sigma)/sigma);
|
|
|
|
else // Verteilung
|
|
|
|
PushDouble(0.5 + gauss((x-mue)/sigma));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScLogNormDist()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double sigma = GetDouble(); // Stdabw
|
|
|
|
double mue = GetDouble(); // Mittelwert
|
|
|
|
double x = GetDouble(); // x
|
2007-07-06 11:35:41 +00:00
|
|
|
if (sigma < 0.0)
|
|
|
|
PushError( errIllegalArgument);
|
|
|
|
else if (sigma == 0.0)
|
|
|
|
PushError( errDivisionByZero);
|
|
|
|
else if (x <= 0.0)
|
2000-09-18 23:16:46 +00:00
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(0.5 + gauss((log(x)-mue)/sigma));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScStdNormDist()
|
|
|
|
{
|
|
|
|
PushDouble(0.5 + gauss(GetDouble()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScExpDist()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double kum = GetDouble(); // 0 oder 1
|
|
|
|
double lambda = GetDouble(); // lambda
|
|
|
|
double x = GetDouble(); // x
|
|
|
|
if (lambda <= 0.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (kum == 0.0) // Dichte
|
|
|
|
{
|
|
|
|
if (x >= 0.0)
|
|
|
|
PushDouble(lambda * exp(-lambda*x));
|
|
|
|
else
|
|
|
|
PushInt(0);
|
|
|
|
}
|
|
|
|
else // Verteilung
|
|
|
|
{
|
|
|
|
if (x > 0.0)
|
|
|
|
PushDouble(1.0 - exp(-lambda*x));
|
|
|
|
else
|
|
|
|
PushInt(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScTDist()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fFlag = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double fDF = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double T = GetDouble();
|
|
|
|
if (fDF < 1.0 || T < 0.0 || (fFlag != 1.0 && fFlag != 2.0) )
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double R = GetTDist(T, fDF);
|
|
|
|
if (fFlag == 1.0)
|
|
|
|
PushDouble(R);
|
|
|
|
else
|
|
|
|
PushDouble(2.0*R);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScFDist()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fF2 = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double fF1 = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double fF = GetDouble();
|
|
|
|
if (fF < 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PushDouble(GetFDist(fF, fF1, fF2));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScChiDist()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fDF = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double fChi = GetDouble();
|
|
|
|
if (fDF < 1.0 || fDF >= 1.0E5 || fChi < 0.0 )
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PushDouble(GetChiDist(fChi, fDF));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScWeibull()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 4 ) )
|
|
|
|
{
|
|
|
|
double kum = GetDouble(); // 0 oder 1
|
|
|
|
double beta = GetDouble(); // beta
|
|
|
|
double alpha = GetDouble(); // alpha
|
|
|
|
double x = GetDouble(); // x
|
|
|
|
if (alpha <= 0.0 || beta <= 0.0 || x < 0.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (kum == 0.0) // Dichte
|
|
|
|
PushDouble(alpha/pow(beta,alpha)*pow(x,alpha-1.0)*
|
|
|
|
exp(-pow(x/beta,alpha)));
|
|
|
|
else // Verteilung
|
|
|
|
PushDouble(1.0 - exp(-pow(x/beta,alpha)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScPoissonDist()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double kum = GetDouble(); // 0 oder 1
|
|
|
|
double lambda = GetDouble(); // Mittelwert
|
2003-03-26 17:07:02 +00:00
|
|
|
double x = ::rtl::math::approxFloor(GetDouble()); // x
|
2000-09-18 23:16:46 +00:00
|
|
|
if (lambda < 0.0 || x < 0.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (kum == 0.0) // Dichte
|
|
|
|
{
|
|
|
|
if (lambda == 0.0)
|
|
|
|
PushInt(0);
|
|
|
|
else
|
2005-09-28 10:38:17 +00:00
|
|
|
{
|
|
|
|
double fPoissonVar = 1.0;
|
|
|
|
for ( double f = 0.0; f < x; ++f )
|
|
|
|
fPoissonVar *= lambda / ( f + 1.0 );
|
|
|
|
PushDouble( fPoissonVar*exp( -lambda ) );
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else // Verteilung
|
|
|
|
{
|
|
|
|
if (lambda == 0.0)
|
|
|
|
PushInt(1);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
double sum = 1.0;
|
|
|
|
double fFak = 1.0;
|
|
|
|
ULONG nEnd = (ULONG) x;
|
|
|
|
for (ULONG i = 1; i <= nEnd; i++)
|
|
|
|
{
|
|
|
|
fFak *= (double)i;
|
|
|
|
sum += pow( lambda, (double)i ) / fFak;
|
|
|
|
}
|
|
|
|
sum *= exp(-lambda);
|
|
|
|
PushDouble(sum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-21 10:54:14 +00:00
|
|
|
/** Local function used in the calculation of the hypergeometric distribution.
|
|
|
|
*/
|
|
|
|
void lcl_PutFactorialElements( ::std::vector< double >& cn, double fLower, double fUpper, double fBase )
|
|
|
|
{
|
|
|
|
for ( double i = fLower; i <= fUpper; ++i )
|
|
|
|
{
|
|
|
|
double fVal = fBase - i;
|
|
|
|
if ( fVal > 1.0 )
|
|
|
|
cn.push_back( fVal );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Calculates a value of the hypergeometric distribution.
|
|
|
|
|
|
|
|
The algorithm is designed to avoid unnecessary multiplications and division
|
|
|
|
by expanding all factorial elements (9 of them). It is done by excluding
|
|
|
|
those ranges that overlap in the numerator and the denominator. This allows
|
|
|
|
for a fast calculation for large values which would otherwise cause an overflow
|
|
|
|
in the intermediate values.
|
|
|
|
|
|
|
|
@author Kohei Yoshida <kohei@openoffice.org>
|
|
|
|
|
|
|
|
@see #i47296#
|
|
|
|
|
|
|
|
*/
|
2000-09-18 23:16:46 +00:00
|
|
|
void ScInterpreter::ScHypGeomDist()
|
|
|
|
{
|
2005-10-21 10:54:14 +00:00
|
|
|
const size_t nMaxArraySize = 500000; // arbitrary max array size
|
|
|
|
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 4 ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
double N = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double M = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double x = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
|
|
|
|
if( (x < 0.0) || (n < x) || (M < x) || (N < n) || (N < M) || (x < n - N + M) )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2005-10-21 10:54:14 +00:00
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef ::std::vector< double > HypContainer;
|
|
|
|
HypContainer cnNumer, cnDenom;
|
|
|
|
|
|
|
|
size_t nEstContainerSize = static_cast<size_t>( x + ::std::min( n, M ) );
|
|
|
|
size_t nMaxSize = ::std::min( cnNumer.max_size(), nMaxArraySize );
|
|
|
|
if ( nEstContainerSize > nMaxSize )
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cnNumer.reserve( nEstContainerSize + 10 );
|
|
|
|
cnDenom.reserve( nEstContainerSize + 10 );
|
|
|
|
|
|
|
|
// Trim coefficient C first
|
|
|
|
double fCNumVarUpper = N - n - M + x - 1.0;
|
|
|
|
double fCDenomVarLower = 1.0;
|
|
|
|
if ( N - n - M + x >= M - x + 1.0 )
|
|
|
|
{
|
|
|
|
fCNumVarUpper = M - x - 1.0;
|
|
|
|
fCDenomVarLower = N - n - 2.0*(M - x) + 1.0;
|
|
|
|
}
|
|
|
|
|
2007-02-27 11:16:29 +00:00
|
|
|
#ifdef DBG_UTIL
|
2005-10-21 10:54:14 +00:00
|
|
|
double fCNumLower = N - n - fCNumVarUpper;
|
2007-02-27 11:16:29 +00:00
|
|
|
#endif
|
2005-10-21 10:54:14 +00:00
|
|
|
double fCDenomUpper = N - n - M + x + 1.0 - fCDenomVarLower;
|
|
|
|
|
|
|
|
double fDNumVarLower = n - M;
|
2000-09-18 23:16:46 +00:00
|
|
|
|
2005-10-21 10:54:14 +00:00
|
|
|
if ( n >= M + 1.0 )
|
|
|
|
{
|
|
|
|
if ( N - M < n + 1.0 )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2005-10-21 10:54:14 +00:00
|
|
|
// Case 1
|
|
|
|
|
|
|
|
if ( N - n < n + 1.0 )
|
|
|
|
{
|
|
|
|
// no overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, N - n - 1.0, N );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// overlap
|
|
|
|
DBG_ASSERT( fCNumLower < n + 1.0, "ScHypGeomDist: wrong assertion" );
|
|
|
|
lcl_PutFactorialElements( cnNumer, N - 2.0*n, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG_ASSERT( fCDenomUpper <= N - M, "ScHypGeomDist: wrong assertion" );
|
|
|
|
|
|
|
|
if ( fCDenomUpper < n - x + 1.0 )
|
|
|
|
// no overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
|
|
|
|
|
|
|
|
fCDenomUpper = n - x;
|
|
|
|
fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
2005-10-21 10:54:14 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// Case 2
|
2000-09-18 23:16:46 +00:00
|
|
|
|
2005-10-21 10:54:14 +00:00
|
|
|
if ( n > M - 1.0 )
|
|
|
|
{
|
|
|
|
// no overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG_ASSERT( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
|
|
|
|
|
|
|
|
if ( fCDenomUpper < n - x + 1.0 )
|
|
|
|
// no overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - n + x, N - M + 1.0 );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcl_PutFactorialElements( cnNumer, N - M - n + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
|
|
|
|
fCDenomUpper = n - x;
|
|
|
|
fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DBG_ASSERT( fCDenomUpper <= M, "ScHypGeomDist: wrong assertion" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( N - M < M + 1.0 )
|
|
|
|
{
|
|
|
|
// Case 3
|
|
|
|
|
|
|
|
if ( N - n < M + 1.0 )
|
|
|
|
{
|
|
|
|
// No overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, N - M - 1.0, N );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lcl_PutFactorialElements( cnNumer, N - n - M, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( n - x + 1.0 > fCDenomUpper )
|
|
|
|
// No overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 1.0, N - M - n + x, N - M + 1.0 );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 1.0, N - M - fCDenomUpper, N - M + 1.0 );
|
|
|
|
|
|
|
|
fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
|
|
|
|
fCDenomUpper = n - x;
|
|
|
|
}
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
2005-10-21 10:54:14 +00:00
|
|
|
// Case 4
|
|
|
|
|
|
|
|
DBG_ASSERT( M >= n - x, "ScHypGeomDist: wrong assertion" );
|
|
|
|
DBG_ASSERT( M - x <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
|
|
|
|
|
|
|
|
if ( N - n < N - M + 1.0 )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2005-10-21 10:54:14 +00:00
|
|
|
// No overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, 0.0, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, M - 1.0, N );
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-10-21 10:54:14 +00:00
|
|
|
// Overlap
|
|
|
|
DBG_ASSERT( fCNumLower <= N - M + 1.0, "ScHypGeomDist: wrong assertion" );
|
|
|
|
|
|
|
|
lcl_PutFactorialElements( cnNumer, M - n, fCNumVarUpper, N - n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, 0.0, n - 1.0, N );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( n - x + 1.0 > fCDenomUpper )
|
|
|
|
// No overlap
|
|
|
|
lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - n + x, N - M + 1.0 );
|
|
|
|
else if ( M >= fCDenomUpper )
|
|
|
|
{
|
|
|
|
lcl_PutFactorialElements( cnNumer, N - 2.0*M + 1.0, N - M - fCDenomUpper, N - M + 1.0 );
|
|
|
|
|
|
|
|
fCDenomUpper = n - x;
|
|
|
|
fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG_ASSERT( M <= fCDenomUpper, "ScHypGeomDist: wrong assertion" );
|
|
|
|
lcl_PutFactorialElements( cnDenom, fCDenomVarLower, N - n - 2.0*M + x,
|
|
|
|
N - n - M + x + 1.0 );
|
|
|
|
|
|
|
|
fCDenomUpper = n - x;
|
|
|
|
fCDenomVarLower = N - M - 2.0*(n - x) + 1.0;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
2005-10-21 10:54:14 +00:00
|
|
|
|
|
|
|
DBG_ASSERT( fCDenomUpper <= n, "ScHypGeomDist: wrong assertion" );
|
|
|
|
|
|
|
|
fDNumVarLower = 0.0;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
2005-10-21 10:54:14 +00:00
|
|
|
|
|
|
|
double nDNumVarUpper = fCDenomUpper < x + 1.0 ? n - x - 1.0 : n - fCDenomUpper - 1.0;
|
|
|
|
double nDDenomVarLower = fCDenomUpper < x + 1.0 ? fCDenomVarLower : N - n - M + 1.0;
|
|
|
|
lcl_PutFactorialElements( cnNumer, fDNumVarLower, nDNumVarUpper, n );
|
|
|
|
lcl_PutFactorialElements( cnDenom, nDDenomVarLower, N - n - M + x, N - n - M + x + 1.0 );
|
|
|
|
|
|
|
|
::std::sort( cnNumer.begin(), cnNumer.end() );
|
|
|
|
::std::sort( cnDenom.begin(), cnDenom.end() );
|
|
|
|
HypContainer::reverse_iterator it1 = cnNumer.rbegin(), it1End = cnNumer.rend();
|
|
|
|
HypContainer::reverse_iterator it2 = cnDenom.rbegin(), it2End = cnDenom.rend();
|
|
|
|
|
|
|
|
double fFactor = 1.0;
|
|
|
|
for ( ; it1 != it1End || it2 != it2End; )
|
|
|
|
{
|
|
|
|
double fEnum = 1.0, fDenom = 1.0;
|
|
|
|
if ( it1 != it1End )
|
|
|
|
fEnum = *it1++;
|
|
|
|
if ( it2 != it2End )
|
|
|
|
fDenom = *it2++;
|
|
|
|
fFactor *= fEnum / fDenom;
|
|
|
|
}
|
|
|
|
|
|
|
|
PushDouble(fFactor);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScGammaDist()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 4 ) )
|
|
|
|
return;
|
|
|
|
double kum = GetDouble(); // 0 oder 1
|
|
|
|
double beta = GetDouble();
|
|
|
|
double alpha = GetDouble();
|
|
|
|
double x = GetDouble(); // x
|
|
|
|
if (x < 0.0 || alpha <= 0.0 || beta <= 0.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (kum == 0.0) // Dichte
|
|
|
|
{
|
|
|
|
double G = GetGamma(alpha);
|
|
|
|
PushDouble(pow(x,alpha-1.0)/exp(x/beta)/pow(beta,alpha)/G);
|
|
|
|
}
|
|
|
|
else // Verteilung
|
|
|
|
PushDouble(GetGammaDist(x, alpha, beta));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScNormInv()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double sigma = GetDouble();
|
|
|
|
double mue = GetDouble();
|
|
|
|
double x = GetDouble();
|
|
|
|
if (sigma <= 0.0 || x < 0.0 || x > 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (x == 0.0 || x == 1.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble(gaussinv(x)*sigma + mue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScSNormInv()
|
|
|
|
{
|
|
|
|
double x = GetDouble();
|
|
|
|
if (x < 0.0 || x > 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else if (x == 0.0 || x == 1.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble(gaussinv(x));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScLogNormInv()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double sigma = GetDouble(); // Stdabw
|
|
|
|
double mue = GetDouble(); // Mittelwert
|
|
|
|
double y = GetDouble(); // y
|
|
|
|
if (sigma <= 0.0 || y <= 0.0 || y >= 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble(exp(mue+sigma*gaussinv(y)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-05 17:26:27 +00:00
|
|
|
class ScGammaDistFunction : public ScDistFunc
|
|
|
|
{
|
|
|
|
ScInterpreter& rInt;
|
|
|
|
double fp, fAlpha, fBeta;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ScGammaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
|
|
|
|
rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
|
|
|
|
|
|
|
|
double GetValue( double x ) const { return fp - rInt.GetGammaDist(x, fAlpha, fBeta); }
|
|
|
|
};
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
void ScInterpreter::ScGammaInv()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
return;
|
|
|
|
double fBeta = GetDouble();
|
|
|
|
double fAlpha = GetDouble();
|
|
|
|
double fP = GetDouble();
|
|
|
|
if (fAlpha <= 0.0 || fBeta <= 0.0 || fP < 0.0 || fP >= 1.0 )
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fP == 0.0)
|
|
|
|
PushInt(0);
|
|
|
|
else
|
|
|
|
{
|
2001-01-05 17:26:27 +00:00
|
|
|
BOOL bConvError;
|
|
|
|
ScGammaDistFunction aFunc( *this, fP, fAlpha, fBeta );
|
|
|
|
double fStart = fAlpha * fBeta;
|
|
|
|
double fVal = lcl_IterateInverse( aFunc, fStart*0.5, fStart, bConvError );
|
|
|
|
if (bConvError)
|
2000-09-18 23:16:46 +00:00
|
|
|
SetError(errNoConvergence);
|
2001-01-05 17:26:27 +00:00
|
|
|
PushDouble(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-05 17:26:27 +00:00
|
|
|
class ScBetaDistFunction : public ScDistFunc
|
|
|
|
{
|
|
|
|
ScInterpreter& rInt;
|
|
|
|
double fp, fAlpha, fBeta;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ScBetaDistFunction( ScInterpreter& rI, double fpVal, double fAlphaVal, double fBetaVal ) :
|
|
|
|
rInt(rI), fp(fpVal), fAlpha(fAlphaVal), fBeta(fBetaVal) {}
|
|
|
|
|
|
|
|
double GetValue( double x ) const { return fp - rInt.GetBetaDist(x, fAlpha, fBeta); }
|
|
|
|
};
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
void ScInterpreter::ScBetaInv()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 3, 5 ) )
|
|
|
|
return;
|
|
|
|
double fP, fA, fB, fAlpha, fBeta;
|
|
|
|
if (nParamCount == 5)
|
|
|
|
fB = GetDouble();
|
|
|
|
else
|
|
|
|
fB = 1.0;
|
|
|
|
if (nParamCount >= 4)
|
|
|
|
fA = GetDouble();
|
|
|
|
else
|
|
|
|
fA = 0.0;
|
|
|
|
fBeta = GetDouble();
|
|
|
|
fAlpha = GetDouble();
|
|
|
|
fP = GetDouble();
|
|
|
|
if (fP < 0.0 || fP >= 1.0 || fA == fB || fAlpha <= 0.0 || fBeta <= 0.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fP == 0.0)
|
|
|
|
PushInt(0);
|
|
|
|
else
|
|
|
|
{
|
2001-01-05 17:26:27 +00:00
|
|
|
BOOL bConvError;
|
|
|
|
ScBetaDistFunction aFunc( *this, fP, fAlpha, fBeta );
|
|
|
|
// 0..1 as range for iteration so it isn't extended beyond the valid range
|
|
|
|
double fVal = lcl_IterateInverse( aFunc, 0.0, 1.0, bConvError );
|
|
|
|
if (bConvError)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
SetError(errNoConvergence);
|
|
|
|
PushInt(0);
|
|
|
|
}
|
|
|
|
else
|
2001-01-05 17:26:27 +00:00
|
|
|
PushDouble(fA + fVal*(fB-fA)); // scale to (A,B)
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
2001-01-05 17:26:27 +00:00
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
// Achtung: T, F und Chi
|
|
|
|
// sind monoton fallend,
|
|
|
|
// deshalb 1-Dist als Funktion
|
|
|
|
|
2001-01-05 17:26:27 +00:00
|
|
|
class ScTDistFunction : public ScDistFunc
|
|
|
|
{
|
|
|
|
ScInterpreter& rInt;
|
|
|
|
double fp, fDF;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ScTDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
|
|
|
|
rInt(rI), fp(fpVal), fDF(fDFVal) {}
|
|
|
|
|
|
|
|
double GetValue( double x ) const { return fp - 2 * rInt.GetTDist(x, fDF); }
|
|
|
|
};
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
void ScInterpreter::ScTInv()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fDF = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double fP = GetDouble();
|
|
|
|
if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
2001-01-05 17:26:27 +00:00
|
|
|
|
|
|
|
BOOL bConvError;
|
|
|
|
ScTDistFunction aFunc( *this, fP, fDF );
|
|
|
|
double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
|
|
|
|
if (bConvError)
|
2000-09-18 23:16:46 +00:00
|
|
|
SetError(errNoConvergence);
|
2001-01-05 17:26:27 +00:00
|
|
|
PushDouble(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
2001-01-05 17:26:27 +00:00
|
|
|
|
|
|
|
class ScFDistFunction : public ScDistFunc
|
|
|
|
{
|
|
|
|
ScInterpreter& rInt;
|
|
|
|
double fp, fF1, fF2;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ScFDistFunction( ScInterpreter& rI, double fpVal, double fF1Val, double fF2Val ) :
|
|
|
|
rInt(rI), fp(fpVal), fF1(fF1Val), fF2(fF2Val) {}
|
|
|
|
|
|
|
|
double GetValue( double x ) const { return fp - rInt.GetFDist(x, fF1, fF2); }
|
|
|
|
};
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
void ScInterpreter::ScFInv()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fF2 = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double fF1 = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double fP = GetDouble();
|
|
|
|
if (fP <= 0.0 || fF1 < 1.0 || fF2 < 1.0 || fF1 >= 1.0E10 || fF2 >= 1.0E10 || fP > 1.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
2001-01-05 17:26:27 +00:00
|
|
|
|
|
|
|
BOOL bConvError;
|
|
|
|
ScFDistFunction aFunc( *this, fP, fF1, fF2 );
|
|
|
|
double fVal = lcl_IterateInverse( aFunc, fF1*0.5, fF1, bConvError );
|
|
|
|
if (bConvError)
|
2000-09-18 23:16:46 +00:00
|
|
|
SetError(errNoConvergence);
|
2001-01-05 17:26:27 +00:00
|
|
|
PushDouble(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
2001-01-05 17:26:27 +00:00
|
|
|
class ScChiDistFunction : public ScDistFunc
|
|
|
|
{
|
|
|
|
ScInterpreter& rInt;
|
|
|
|
double fp, fDF;
|
|
|
|
|
|
|
|
public:
|
|
|
|
ScChiDistFunction( ScInterpreter& rI, double fpVal, double fDFVal ) :
|
|
|
|
rInt(rI), fp(fpVal), fDF(fDFVal) {}
|
|
|
|
|
|
|
|
double GetValue( double x ) const { return fp - rInt.GetChiDist(x, fDF); }
|
|
|
|
};
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
void ScInterpreter::ScChiInv()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fDF = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double fP = GetDouble();
|
|
|
|
if (fDF < 1.0 || fDF >= 1.0E5 || fP <= 0.0 || fP > 1.0 )
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
2001-01-05 17:26:27 +00:00
|
|
|
|
|
|
|
BOOL bConvError;
|
|
|
|
ScChiDistFunction aFunc( *this, fP, fDF );
|
|
|
|
double fVal = lcl_IterateInverse( aFunc, fDF*0.5, fDF, bConvError );
|
|
|
|
if (bConvError)
|
2000-09-18 23:16:46 +00:00
|
|
|
SetError(errNoConvergence);
|
2001-01-05 17:26:27 +00:00
|
|
|
PushDouble(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************/
|
|
|
|
|
|
|
|
void ScInterpreter::ScConfidence()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
double n = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
double sigma = GetDouble();
|
|
|
|
double alpha = GetDouble();
|
|
|
|
if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
|
|
|
|
SetIllegalArgument();
|
|
|
|
else
|
|
|
|
PushDouble( gaussinv(1.0-alpha/2.0) * sigma/sqrt(n) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScZTest()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
|
|
|
|
return;
|
2007-02-27 11:16:29 +00:00
|
|
|
double sigma = 0.0, mue, x;
|
2000-09-18 23:16:46 +00:00
|
|
|
if (nParamCount == 3)
|
|
|
|
{
|
|
|
|
sigma = GetDouble();
|
|
|
|
if (sigma <= 0.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
x = GetDouble();
|
|
|
|
|
|
|
|
double fSum = 0.0;
|
|
|
|
double fSumSqr = 0.0;
|
|
|
|
double fVal;
|
|
|
|
double rValCount = 0.0;
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
{
|
|
|
|
fVal = GetDouble();
|
|
|
|
fSum += fVal;
|
|
|
|
fSumSqr += fVal*fVal;
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
ScAddress aAdr;
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
fVal = GetCellValue( aAdr, pCell );
|
|
|
|
fSum += fVal;
|
|
|
|
fSumSqr += fVal*fVal;
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
ScRange aRange;
|
|
|
|
USHORT nErr = 0;
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
ScValueIterator aValIter(pDok, aRange, glSubTotal);
|
|
|
|
if (aValIter.GetFirst(fVal, nErr))
|
|
|
|
{
|
|
|
|
fSum += fVal;
|
|
|
|
fSumSqr += fVal*fVal;
|
|
|
|
rValCount++;
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
|
|
|
|
{
|
|
|
|
fSum += fVal;
|
|
|
|
fSumSqr += fVal*fVal;
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for ( SCSIZE i = 0; i < nCount; i++ )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
fVal= pMat->GetDouble(i);
|
|
|
|
fSum += fVal;
|
|
|
|
fSumSqr += fVal * fVal;
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nCount; i++)
|
2001-04-27 21:44:26 +00:00
|
|
|
if (!pMat->IsString(i))
|
|
|
|
{
|
|
|
|
fVal= pMat->GetDouble(i);
|
|
|
|
fSum += fVal;
|
|
|
|
fSumSqr += fVal * fVal;
|
|
|
|
rValCount++;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default : SetError(errIllegalParameter); break;
|
|
|
|
}
|
|
|
|
if (rValCount <= 1.0)
|
2007-07-06 11:35:41 +00:00
|
|
|
PushError( errDivisionByZero);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mue = fSum/rValCount;
|
|
|
|
if (nParamCount != 3)
|
|
|
|
sigma = (fSumSqr - fSum*fSum/rValCount)/(rValCount-1.0);
|
|
|
|
|
|
|
|
PushDouble(0.5 - gauss((mue-x)/sqrt(sigma/rValCount)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScTTest()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 4 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fTyp = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
double fAnz = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (fAnz != 1.0 && fAnz != 2.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fT, fF;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
|
|
|
SCSIZE i, j;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (fTyp == 1.0)
|
|
|
|
{
|
|
|
|
if (nC1 != nC2 || nR1 != nR2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSum1 = 0.0;
|
|
|
|
double fSum2 = 0.0;
|
|
|
|
double fSumSqrD = 0.0;
|
|
|
|
double fVal1, fVal2;
|
|
|
|
for (i = 0; i < nC1; i++)
|
|
|
|
for (j = 0; j < nR1; j++)
|
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal1 = pMat1->GetDouble(i,j);
|
|
|
|
fVal2 = pMat2->GetDouble(i,j);
|
|
|
|
fSum1 += fVal1;
|
|
|
|
fSum2 += fVal2;
|
|
|
|
fSumSqrD += (fVal1 - fVal2)*(fVal1 - fVal2);
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 1.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fT = sqrt(fCount-1.0) * fabs(fSum1 - fSum2) /
|
|
|
|
sqrt(fCount * fSumSqrD - (fSum1-fSum2)*(fSum1-fSum2));
|
|
|
|
fF = fCount - 1.0;
|
|
|
|
}
|
|
|
|
else if (fTyp == 2.0)
|
|
|
|
{
|
|
|
|
double fCount1 = 0.0;
|
|
|
|
double fCount2 = 0.0;
|
|
|
|
double fSum1 = 0.0;
|
|
|
|
double fSumSqr1 = 0.0;
|
|
|
|
double fSum2 = 0.0;
|
|
|
|
double fSumSqr2 = 0.0;
|
|
|
|
double fVal;
|
|
|
|
for (i = 0; i < nC1; i++)
|
|
|
|
for (j = 0; j < nR1; j++)
|
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal = pMat1->GetDouble(i,j);
|
|
|
|
fSum1 += fVal;
|
|
|
|
fSumSqr1 += fVal * fVal;
|
|
|
|
fCount1++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < nC2; i++)
|
|
|
|
for (j = 0; j < nR2; j++)
|
|
|
|
{
|
|
|
|
if (!pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal = pMat2->GetDouble(i,j);
|
|
|
|
fSum2 += fVal;
|
|
|
|
fSumSqr2 += fVal * fVal;
|
|
|
|
fCount2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount1 < 2.0 || fCount2 < 2.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
// alter Templin-Code
|
|
|
|
double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
|
|
|
|
double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
|
|
|
|
if (fS1 + fS2 == 0.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
|
|
|
|
fF = fCount1 + fCount2 - 2;
|
|
|
|
#else
|
|
|
|
// laut Bronstein-Semendjajew
|
|
|
|
double fS1 = (fSumSqr1 - fSum1*fSum1/fCount1) / (fCount1 - 1.0); // Varianz
|
|
|
|
double fS2 = (fSumSqr2 - fSum2*fSum2/fCount2) / (fCount2 - 1.0);
|
|
|
|
fT = fabs( fSum1/fCount1 - fSum2/fCount2 ) /
|
|
|
|
sqrt( (fCount1-1.0)*fS1 + (fCount2-1.0)*fS2 ) *
|
|
|
|
sqrt( fCount1*fCount2*(fCount1+fCount2-2)/(fCount1+fCount2) );
|
|
|
|
fF = fCount1 + fCount2 - 2;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (fTyp == 3.0)
|
|
|
|
{
|
|
|
|
double fCount1 = 0.0;
|
|
|
|
double fCount2 = 0.0;
|
|
|
|
double fSum1 = 0.0;
|
|
|
|
double fSumSqr1 = 0.0;
|
|
|
|
double fSum2 = 0.0;
|
|
|
|
double fSumSqr2 = 0.0;
|
|
|
|
double fVal;
|
|
|
|
for (i = 0; i < nC1; i++)
|
|
|
|
for (j = 0; j < nR1; j++)
|
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal = pMat1->GetDouble(i,j);
|
|
|
|
fSum1 += fVal;
|
|
|
|
fSumSqr1 += fVal * fVal;
|
|
|
|
fCount1++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < nC2; i++)
|
|
|
|
for (j = 0; j < nR2; j++)
|
|
|
|
{
|
|
|
|
if (!pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal = pMat2->GetDouble(i,j);
|
|
|
|
fSum2 += fVal;
|
|
|
|
fSumSqr2 += fVal * fVal;
|
|
|
|
fCount2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount1 < 2.0 || fCount2 < 2.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0)/fCount1;
|
|
|
|
double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0)/fCount2;
|
|
|
|
if (fS1 + fS2 == 0.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
fT = fabs(fSum1/fCount1 - fSum2/fCount2)/sqrt(fS1+fS2);
|
|
|
|
double c = fS1/(fS1+fS2);
|
2003-03-26 17:07:02 +00:00
|
|
|
// s.u. fF = ::rtl::math::approxFloor(1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0)));
|
|
|
|
// fF = ::rtl::math::approxFloor((fS1+fS2)*(fS1+fS2)/(fS1*fS1/(fCount1-1.0) + fS2*fS2/(fCount2-1.0)));
|
2000-09-18 23:16:46 +00:00
|
|
|
|
|
|
|
// GetTDist wird mit GetBetaDist berechnet und kommt auch mit nicht ganzzahligen
|
|
|
|
// Freiheitsgraden klar. Dann stimmt das Ergebnis auch mit Excel ueberein (#52406#):
|
|
|
|
fF = 1.0/(c*c/(fCount1-1.0)+(1.0-c)*(1.0-c)/(fCount2-1.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fAnz == 1.0)
|
|
|
|
PushDouble(GetTDist(fT, fF));
|
|
|
|
else
|
|
|
|
PushDouble(2.0*GetTDist(fT, fF));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScFTest()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
|
|
|
SCSIZE i, j;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
double fCount1 = 0.0;
|
|
|
|
double fCount2 = 0.0;
|
|
|
|
double fSum1 = 0.0;
|
|
|
|
double fSumSqr1 = 0.0;
|
|
|
|
double fSum2 = 0.0;
|
|
|
|
double fSumSqr2 = 0.0;
|
|
|
|
double fVal;
|
|
|
|
for (i = 0; i < nC1; i++)
|
|
|
|
for (j = 0; j < nR1; j++)
|
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal = pMat1->GetDouble(i,j);
|
|
|
|
fSum1 += fVal;
|
|
|
|
fSumSqr1 += fVal * fVal;
|
|
|
|
fCount1++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < nC2; i++)
|
|
|
|
for (j = 0; j < nR2; j++)
|
|
|
|
{
|
|
|
|
if (!pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fVal = pMat2->GetDouble(i,j);
|
|
|
|
fSum2 += fVal;
|
|
|
|
fSumSqr2 += fVal * fVal;
|
|
|
|
fCount2++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount1 < 2.0 || fCount2 < 2.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fS1 = (fSumSqr1-fSum1*fSum1/fCount1)/(fCount1-1.0);
|
|
|
|
double fS2 = (fSumSqr2-fSum2*fSum2/fCount2)/(fCount2-1.0);
|
|
|
|
if (fS1 == 0.0 || fS2 == 0.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fF, fF1, fF2;
|
|
|
|
if (fS1 > fS2)
|
|
|
|
{
|
|
|
|
fF = fS1/fS2;
|
|
|
|
fF1 = fCount1-1.0;
|
|
|
|
fF2 = fCount2-1.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fF = fS2/fS1;
|
|
|
|
fF1 = fCount2-1.0;
|
|
|
|
fF2 = fCount1-1.0;
|
|
|
|
}
|
|
|
|
PushDouble(2.0*GetFDist(fF, fF1, fF2));
|
|
|
|
/*
|
|
|
|
double Z = (pow(fF,1.0/3.0)*(1.0-2.0/(9.0*fF2)) - (1.0-2.0/(9.0*fF1))) /
|
|
|
|
sqrt(2.0/(9.0*fF1) + pow(fF,2.0/3.0)*2.0/(9.0*fF2));
|
|
|
|
PushDouble(1.0-2.0*gauss(Z));
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScChiTest()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fChi = 0.0;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE i, j;
|
2000-09-18 23:16:46 +00:00
|
|
|
double fValX, fValE;
|
|
|
|
for (i = 0; i < nC1; i++)
|
|
|
|
for (j = 0; j < nR1; j++)
|
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValE = pMat2->GetDouble(i,j);
|
|
|
|
fChi += (fValX-fValE)*(fValX-fValE)/fValE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
double fDF;
|
|
|
|
if (nC1 == 1 || nR1 == 1)
|
|
|
|
{
|
|
|
|
fDF = (double)(nC1*nR1 - 1);
|
|
|
|
if (fDF == 0.0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fDF = (double)(nC1-1)*(double)(nR1-1);
|
|
|
|
PushDouble(GetChiDist(fChi, fDF));
|
|
|
|
/*
|
|
|
|
double fX, fS, fT, fG;
|
|
|
|
fX = 1.0;
|
|
|
|
for (double fi = fDF; fi >= 2.0; fi -= 2.0)
|
|
|
|
fX *= fChi/fi;
|
|
|
|
fX *= exp(-fChi/2.0);
|
|
|
|
if (fmod(fDF, 2.0) != 0.0)
|
|
|
|
fX *= sqrt(2.0*fChi/F_PI);
|
|
|
|
fS = 1.0;
|
|
|
|
fT = 1.0;
|
|
|
|
fG = fDF;
|
|
|
|
while (fT >= 1.0E-7)
|
|
|
|
{
|
|
|
|
fG += 2.0;
|
|
|
|
fT *= fChi/fG;
|
|
|
|
fS += fT;
|
|
|
|
}
|
|
|
|
PushDouble(1.0 - fX*fS);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScKurt()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCountMin( nParamCount, 1 ) )
|
|
|
|
return;
|
|
|
|
USHORT i;
|
|
|
|
double fSum = 0.0;
|
2004-11-15 15:35:44 +00:00
|
|
|
double vSum = 0.0;
|
|
|
|
std::vector<double> values;
|
2000-09-18 23:16:46 +00:00
|
|
|
double fCount = 0.0;
|
2004-11-15 15:35:44 +00:00
|
|
|
double fVal = 0.0;
|
2000-09-18 23:16:46 +00:00
|
|
|
ScAddress aAdr;
|
|
|
|
ScRange aRange;
|
|
|
|
for (i = 0; i < nParamCount; i++)
|
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
{
|
|
|
|
fVal = GetDouble();
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
fVal = GetCellValue( aAdr, pCell );
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
USHORT nErr = 0;
|
|
|
|
ScValueIterator aValIter(pDok, aRange);
|
|
|
|
if (aValIter.GetFirst(fVal, nErr))
|
|
|
|
{
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
|
|
|
|
{
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
fVal = pMat->GetDouble(nElem);
|
2001-04-27 21:44:26 +00:00
|
|
|
fSum += fVal;
|
2007-02-27 11:16:29 +00:00
|
|
|
values.push_back(fVal);
|
2001-04-27 21:44:26 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
|
|
|
if (!pMat->IsString(nElem))
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
fVal = pMat->GetDouble(nElem);
|
2000-09-18 23:16:46 +00:00
|
|
|
fSum += fVal;
|
2007-02-27 11:16:29 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
SetError(errIllegalParameter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-11-15 15:35:44 +00:00
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
if (nGlobalError)
|
|
|
|
{
|
|
|
|
PushInt(0);
|
|
|
|
return;
|
|
|
|
}
|
2004-11-15 15:35:44 +00:00
|
|
|
|
2007-07-06 11:35:41 +00:00
|
|
|
if (fCount == 0.0)
|
|
|
|
{
|
|
|
|
PushError( errDivisionByZero);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
double fMean = fSum / fCount;
|
2004-11-15 15:35:44 +00:00
|
|
|
|
|
|
|
for (i = 0; i < values.size(); i++)
|
|
|
|
vSum += (values[i] - fMean) * (values[i] - fMean);
|
|
|
|
|
|
|
|
double fStdDev = sqrt(vSum / (fCount - 1.0));
|
|
|
|
double dx = 0.0;
|
|
|
|
double xpower4 = 0.0;
|
|
|
|
|
2007-07-06 11:35:41 +00:00
|
|
|
if (fStdDev == 0.0)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2007-07-06 11:35:41 +00:00
|
|
|
PushError( errDivisionByZero);
|
2004-11-15 15:35:44 +00:00
|
|
|
return;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
2004-11-15 15:35:44 +00:00
|
|
|
|
|
|
|
for (i = 0; i < values.size(); i++)
|
|
|
|
{
|
|
|
|
dx = (values[i] - fMean) / fStdDev;
|
|
|
|
xpower4 = xpower4 + (dx * dx * dx * dx);
|
|
|
|
}
|
|
|
|
|
|
|
|
double k_d = (fCount - 2.0) * (fCount - 3.0);
|
|
|
|
double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * k_d);
|
|
|
|
double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;
|
|
|
|
|
|
|
|
PushDouble(xpower4 * k_l - k_t);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScHarMean()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
double nVal = 0.0;
|
2004-03-08 10:48:19 +00:00
|
|
|
double nValCount = 0.0;
|
2000-09-18 23:16:46 +00:00
|
|
|
ScAddress aAdr;
|
|
|
|
ScRange aRange;
|
|
|
|
for (short i = 0; i < nParamCount && (nGlobalError == 0); i++)
|
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
{
|
|
|
|
double x = GetDouble();
|
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += 1.0/x;
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
double x = GetCellValue( aAdr, pCell );
|
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += 1.0/x;
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
USHORT nErr = 0;
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
double nCellVal;
|
|
|
|
ScValueIterator aValIter(pDok, aRange, glSubTotal);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
if (nCellVal > 0.0)
|
|
|
|
{
|
|
|
|
nVal += 1.0/nCellVal;
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
if (nCellVal > 0.0)
|
|
|
|
{
|
|
|
|
nVal += 1.0/nCellVal;
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
double x = pMat->GetDouble(nElem);
|
2001-04-27 21:44:26 +00:00
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += 1.0/x;
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2001-04-27 21:44:26 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2001-04-27 21:44:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
|
|
|
if (!pMat->IsString(nElem))
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
double x = pMat->GetDouble(nElem);
|
2000-09-18 23:16:46 +00:00
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += 1.0/x;
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default : SetError(errIllegalParameter); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nGlobalError == 0)
|
2004-03-08 10:48:19 +00:00
|
|
|
PushDouble((double)nValCount/nVal);
|
|
|
|
else
|
|
|
|
PushInt(0);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScGeoMean()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
double nVal = 0.0;
|
2004-03-08 10:48:19 +00:00
|
|
|
double nValCount = 0.0;
|
2000-09-18 23:16:46 +00:00
|
|
|
ScAddress aAdr;
|
|
|
|
ScRange aRange;
|
2004-11-15 15:35:44 +00:00
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
for (short i = 0; i < nParamCount && (nGlobalError == 0); i++)
|
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
{
|
|
|
|
double x = GetDouble();
|
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += log(x);
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
double x = GetCellValue( aAdr, pCell );
|
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += log(x);
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
USHORT nErr = 0;
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
double nCellVal;
|
|
|
|
ScValueIterator aValIter(pDok, aRange, glSubTotal);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
if (nCellVal > 0.0)
|
|
|
|
{
|
|
|
|
nVal += log(nCellVal);
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
if (nCellVal > 0.0)
|
|
|
|
{
|
|
|
|
nVal += log(nCellVal);
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2004-11-15 15:35:44 +00:00
|
|
|
for (SCSIZE ui = 0; ui < nCount; ui++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2004-11-15 15:35:44 +00:00
|
|
|
double x = pMat->GetDouble(ui);
|
2001-04-27 21:44:26 +00:00
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += log(x);
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2001-04-27 21:44:26 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2001-04-27 21:44:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-11-15 15:35:44 +00:00
|
|
|
for (SCSIZE ui = 0; ui < nCount; ui++)
|
|
|
|
if (!pMat->IsString(ui))
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2004-11-15 15:35:44 +00:00
|
|
|
double x = pMat->GetDouble(ui);
|
2000-09-18 23:16:46 +00:00
|
|
|
if (x > 0.0)
|
|
|
|
{
|
|
|
|
nVal += log(x);
|
2004-03-08 10:48:19 +00:00
|
|
|
nValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default : SetError(errIllegalParameter); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nGlobalError == 0)
|
2004-11-15 15:35:44 +00:00
|
|
|
PushDouble(exp(nVal / nValCount));
|
2004-03-08 10:48:19 +00:00
|
|
|
else
|
|
|
|
PushInt(0);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScStandard()
|
|
|
|
{
|
|
|
|
if ( MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
{
|
|
|
|
double sigma = GetDouble();
|
|
|
|
double mue = GetDouble();
|
|
|
|
double x = GetDouble();
|
2007-07-06 11:35:41 +00:00
|
|
|
if (sigma < 0.0)
|
|
|
|
PushError( errIllegalArgument);
|
|
|
|
else if (sigma == 0.0)
|
|
|
|
PushError( errDivisionByZero);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
PushDouble((x-mue)/sigma);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScSkew()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCountMin( nParamCount, 1 ) )
|
|
|
|
return;
|
|
|
|
USHORT i;
|
|
|
|
double fSum = 0.0;
|
2004-11-15 15:35:44 +00:00
|
|
|
double vSum = 0.0;
|
|
|
|
std::vector<double> values;
|
2000-09-18 23:16:46 +00:00
|
|
|
double fCount = 0.0;
|
2004-11-15 15:35:44 +00:00
|
|
|
double fVal = 0.0;
|
2000-09-18 23:16:46 +00:00
|
|
|
ScAddress aAdr;
|
|
|
|
ScRange aRange;
|
|
|
|
for (i = 0; i < nParamCount; i++)
|
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
{
|
|
|
|
fVal = GetDouble();
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
fVal = GetCellValue( aAdr, pCell );
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
USHORT nErr = 0;
|
|
|
|
ScValueIterator aValIter(pDok, aRange);
|
|
|
|
if (aValIter.GetFirst(fVal, nErr))
|
|
|
|
{
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(fVal, nErr))
|
|
|
|
{
|
|
|
|
fSum += fVal;
|
2004-11-15 15:35:44 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
fVal = pMat->GetDouble(nElem);
|
2001-04-27 21:44:26 +00:00
|
|
|
fSum += fVal;
|
2007-02-27 11:16:29 +00:00
|
|
|
values.push_back(fVal);
|
2001-04-27 21:44:26 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
|
|
|
if (!pMat->IsString(nElem))
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
fVal = pMat->GetDouble(nElem);
|
2000-09-18 23:16:46 +00:00
|
|
|
fSum += fVal;
|
2007-02-27 11:16:29 +00:00
|
|
|
values.push_back(fVal);
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
SetError(errIllegalParameter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-11-15 15:35:44 +00:00
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
if (nGlobalError)
|
|
|
|
{
|
|
|
|
PushInt(0);
|
|
|
|
return;
|
|
|
|
}
|
2004-11-15 15:35:44 +00:00
|
|
|
|
2000-09-18 23:16:46 +00:00
|
|
|
double fMean = fSum / fCount;
|
2004-11-15 15:35:44 +00:00
|
|
|
|
|
|
|
for (i = 0; i < values.size(); i++)
|
|
|
|
vSum += (values[i] - fMean) * (values[i] - fMean);
|
|
|
|
|
|
|
|
double fStdDev = sqrt(vSum / (fCount - 1.0));
|
|
|
|
double dx = 0.0;
|
|
|
|
double xcube = 0.0;
|
|
|
|
|
|
|
|
if (fStdDev == 0)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2004-11-15 15:35:44 +00:00
|
|
|
SetError(errIllegalArgument);
|
|
|
|
return;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
2004-11-15 15:35:44 +00:00
|
|
|
|
|
|
|
for (i = 0; i < values.size(); i++)
|
|
|
|
{
|
|
|
|
dx = (values[i] - fMean) / fStdDev;
|
|
|
|
xcube = xcube + (dx * dx * dx);
|
|
|
|
}
|
|
|
|
|
|
|
|
PushDouble(((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0));
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScMedian()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCountMin( nParamCount, 1 ) )
|
|
|
|
return;
|
|
|
|
double* pSortArray = NULL;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(nParamCount, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (nSize % 2 == 0)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble((pSortArray[nSize/2-1]+pSortArray[nSize/2])/2.0);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[(nSize-1)/2]);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScPercentile()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
|
|
|
double alpha = GetDouble();
|
|
|
|
if (alpha < 0.0 || alpha > 1.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double* pSortArray = NULL;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(1, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (nSize == 1)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[0]);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nIndex = (SCSIZE)::rtl::math::approxFloor(alpha*(nSize-1));
|
2003-03-26 17:07:02 +00:00
|
|
|
double fDiff = alpha*(nSize-1) - ::rtl::math::approxFloor(alpha*(nSize-1));
|
2007-02-27 11:16:29 +00:00
|
|
|
DBG_ASSERT(nIndex < nSize, "ScPercentile: falscher Index (1)");
|
2000-09-18 23:16:46 +00:00
|
|
|
if (fDiff == 0.0)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nIndex]);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG_ASSERT(nIndex < nSize-1, "ScPercentile: falscher Index(2)");
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nIndex] +
|
|
|
|
fDiff*(pSortArray[nIndex+1]-pSortArray[nIndex]));
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScQuartile()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2003-03-26 17:07:02 +00:00
|
|
|
double fFlag = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (fFlag < 0.0 || fFlag > 4.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double* pSortArray = NULL;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(1, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (nSize == 1)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[0]);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fFlag == 0.0)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[0]);
|
2000-09-18 23:16:46 +00:00
|
|
|
else if (fFlag == 1.0)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nIndex = (SCSIZE)::rtl::math::approxFloor(0.25*(nSize-1));
|
2003-03-26 17:07:02 +00:00
|
|
|
double fDiff = 0.25*(nSize-1) - ::rtl::math::approxFloor(0.25*(nSize-1));
|
2007-02-27 11:16:29 +00:00
|
|
|
DBG_ASSERT(nIndex < nSize, "ScQuartile: falscher Index (1)");
|
2000-09-18 23:16:46 +00:00
|
|
|
if (fDiff == 0.0)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nIndex]);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG_ASSERT(nIndex < nSize-1, "ScQuartile: falscher Index(2)");
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nIndex] +
|
|
|
|
fDiff*(pSortArray[nIndex+1]-pSortArray[nIndex]));
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (fFlag == 2.0)
|
|
|
|
{
|
|
|
|
if (nSize % 2 == 0)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble((pSortArray[nSize/2-1]+pSortArray[nSize/2])/2.0);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[(nSize-1)/2]);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else if (fFlag == 3.0)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nIndex = (SCSIZE)::rtl::math::approxFloor(0.75*(nSize-1));
|
2003-03-26 17:07:02 +00:00
|
|
|
double fDiff = 0.75*(nSize-1) - ::rtl::math::approxFloor(0.75*(nSize-1));
|
2007-02-27 11:16:29 +00:00
|
|
|
DBG_ASSERT(nIndex < nSize, "ScQuartile: falscher Index (3)");
|
2000-09-18 23:16:46 +00:00
|
|
|
if (fDiff == 0.0)
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nIndex]);
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG_ASSERT(nIndex < nSize-1, "ScQuartile: falscher Index(4)");
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nIndex] +
|
|
|
|
fDiff*(pSortArray[nIndex+1]-pSortArray[nIndex]));
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nSize-1]);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScModalValue()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCountMin( nParamCount, 1 ) )
|
|
|
|
return;
|
|
|
|
double* pSortArray = NULL;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(nParamCount, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
SCSIZE nMaxIndex = 0, nMax = 1, nCount = 1;
|
2004-06-04 09:36:51 +00:00
|
|
|
double nOldVal = pSortArray[0];
|
|
|
|
SCSIZE i;
|
2003-12-01 16:51:14 +00:00
|
|
|
|
|
|
|
for ( i = 1; i < nSize; i++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
if (pSortArray[i] == nOldVal)
|
2000-09-18 23:16:46 +00:00
|
|
|
nCount++;
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
nOldVal = pSortArray[i];
|
2000-09-18 23:16:46 +00:00
|
|
|
if (nCount > nMax)
|
|
|
|
{
|
|
|
|
nMax = nCount;
|
|
|
|
nMaxIndex = i-1;
|
|
|
|
}
|
|
|
|
nCount = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nCount > nMax)
|
|
|
|
{
|
|
|
|
nMax = nCount;
|
|
|
|
nMaxIndex = i-1;
|
|
|
|
}
|
|
|
|
if (nMax == 1 && nCount == 1)
|
|
|
|
SetNoValue();
|
|
|
|
else if (nMax == 1)
|
|
|
|
PushDouble(nOldVal);
|
|
|
|
else
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(pSortArray[nMaxIndex]);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScLarge()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-06-04 09:36:51 +00:00
|
|
|
double f = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
if (f < 1.0)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE k = static_cast<SCSIZE>(f);
|
|
|
|
double* pSortArray = NULL;
|
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(1, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError || nSize < k)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
#if 0
|
2000-09-18 23:16:46 +00:00
|
|
|
/*
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = 1;
|
|
|
|
double nOldVal = pSortArray[nSize-1];
|
2000-09-18 23:16:46 +00:00
|
|
|
for (long i = nSize-2; i >= 0 && nCount < k; i--)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
if (pSortArray[i] != nOldVal)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
nCount++;
|
2004-06-04 09:36:51 +00:00
|
|
|
nOldVal = pSortArray[i];
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nCount < k)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble(nOldVal);
|
|
|
|
*/
|
2004-06-04 09:36:51 +00:00
|
|
|
#endif
|
|
|
|
PushDouble( pSortArray[ nSize-k ] );
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScSmall()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-06-04 09:36:51 +00:00
|
|
|
double f = ::rtl::math::approxFloor(GetDouble());
|
|
|
|
if (f < 1.0)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE k = static_cast<SCSIZE>(f);
|
|
|
|
double* pSortArray = NULL;
|
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(1, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError || nSize < k)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
#if 0
|
2000-09-18 23:16:46 +00:00
|
|
|
/*
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = 1;
|
|
|
|
double nOldVal = pSortArray[0];
|
|
|
|
for (SCSIZE i = 1; i < nSize && nCount < k; i++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
if (pSortArray[i] != nOldVal)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
nCount++;
|
2004-06-04 09:36:51 +00:00
|
|
|
nOldVal = pSortArray[i];
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nCount < k)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble(nOldVal);
|
|
|
|
*/
|
2004-06-04 09:36:51 +00:00
|
|
|
#endif
|
|
|
|
PushDouble( pSortArray[ k-1 ] );
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScPercentrank()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 2 ) )
|
|
|
|
return;
|
2004-06-04 09:36:51 +00:00
|
|
|
#if 0
|
2000-09-18 23:16:46 +00:00
|
|
|
/* wird nicht unterstuetzt
|
|
|
|
double fPrec;
|
|
|
|
if (nParamCount == 3)
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
fPrec = ::rtl::math::approxFloor(GetDouble());
|
2000-09-18 23:16:46 +00:00
|
|
|
if (fPrec < 1.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fPrec = 3.0;
|
|
|
|
*/
|
2004-06-04 09:36:51 +00:00
|
|
|
#endif
|
2000-09-18 23:16:46 +00:00
|
|
|
double fNum = GetDouble();
|
|
|
|
double* pSortArray = NULL;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(1, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
if (fNum < pSortArray[0] || fNum > pSortArray[nSize-1])
|
2000-09-18 23:16:46 +00:00
|
|
|
SetNoValue();
|
|
|
|
else if ( nSize == 1 )
|
2004-06-04 09:36:51 +00:00
|
|
|
PushDouble(1.0); // fNum == pSortArray[0], see test above
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
double fRes;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nOldCount = 0;
|
|
|
|
double fOldVal = pSortArray[0];
|
|
|
|
SCSIZE i;
|
|
|
|
for (i = 1; i < nSize && pSortArray[i] < fNum; i++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
if (pSortArray[i] != fOldVal)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
nOldCount = i;
|
2004-06-04 09:36:51 +00:00
|
|
|
fOldVal = pSortArray[i];
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
if (pSortArray[i] != fOldVal)
|
2000-09-18 23:16:46 +00:00
|
|
|
nOldCount = i;
|
2004-06-04 09:36:51 +00:00
|
|
|
if (fNum == pSortArray[i])
|
2000-09-18 23:16:46 +00:00
|
|
|
fRes = (double)nOldCount/(double)(nSize-1);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// #75312# nOldCount is the count of smaller entries
|
2004-06-04 09:36:51 +00:00
|
|
|
// fNum is between pSortArray[nOldCount-1] and pSortArray[nOldCount]
|
2000-09-18 23:16:46 +00:00
|
|
|
// use linear interpolation to find a position between the entries
|
|
|
|
|
|
|
|
if ( nOldCount == 0 )
|
|
|
|
{
|
|
|
|
DBG_ERROR("should not happen");
|
|
|
|
fRes = 0.0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
double fFract = ( fNum - pSortArray[nOldCount-1] ) /
|
|
|
|
( pSortArray[nOldCount] - pSortArray[nOldCount-1] );
|
2000-09-18 23:16:46 +00:00
|
|
|
fRes = ( (double)(nOldCount-1)+fFract )/(double)(nSize-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PushDouble(fRes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScTrimMean()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
|
|
|
double alpha = GetDouble();
|
|
|
|
if (alpha < 0.0 || alpha >= 1.0)
|
|
|
|
{
|
|
|
|
SetIllegalArgument();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double* pSortArray = NULL;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nSize = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
GetSortArray(1, &pSortArray, nSize);
|
|
|
|
if (!pSortArray || nSize == 0 || nGlobalError)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
{
|
2003-03-26 17:07:02 +00:00
|
|
|
ULONG nIndex = (ULONG) ::rtl::math::approxFloor(alpha*(double)nSize);
|
2000-09-18 23:16:46 +00:00
|
|
|
if (nIndex % 2 != 0)
|
|
|
|
nIndex--;
|
|
|
|
nIndex /= 2;
|
2007-02-27 11:16:29 +00:00
|
|
|
DBG_ASSERT(nIndex < nSize, "ScTrimMean: falscher Index");
|
2000-09-18 23:16:46 +00:00
|
|
|
double fSum = 0.0;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = nIndex; i < nSize-nIndex; i++)
|
|
|
|
fSum += pSortArray[i];
|
2000-09-18 23:16:46 +00:00
|
|
|
PushDouble(fSum/(double)(nSize-2*nIndex));
|
|
|
|
}
|
|
|
|
if (pSortArray)
|
|
|
|
delete [] pSortArray;
|
|
|
|
}
|
|
|
|
|
2004-06-04 09:36:51 +00:00
|
|
|
void ScInterpreter::GetSortArray(BYTE nParamCount, double** ppSortArray, SCSIZE& nSize)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
*ppSortArray = NULL;
|
|
|
|
nSize = 0;
|
|
|
|
|
|
|
|
USHORT SaveSP = sp;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE rValCount = 0;
|
2000-09-18 23:16:46 +00:00
|
|
|
ScAddress aAdr;
|
|
|
|
ScRange aRange;
|
2004-06-04 09:36:51 +00:00
|
|
|
BYTE nParam;
|
|
|
|
for (nParam = 0; nParam < nParamCount; nParam++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
2001-04-27 21:44:26 +00:00
|
|
|
PopDouble();
|
2000-09-18 23:16:46 +00:00
|
|
|
rValCount++;
|
2001-04-27 20:11:04 +00:00
|
|
|
break;
|
2000-09-18 23:16:46 +00:00
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
USHORT nErr = 0;
|
|
|
|
double nCellVal;
|
|
|
|
ScValueIterator aValIter(pDok, aRange);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
rValCount++;
|
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
|
|
|
|
rValCount++;
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
2001-04-27 21:44:26 +00:00
|
|
|
rValCount += nCount;
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nCount; i++)
|
2001-04-27 21:44:26 +00:00
|
|
|
if (!pMat->IsString(i))
|
|
|
|
rValCount++;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
SetError(errIllegalParameter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rValCount > MAX_ANZ_DOUBLE_FOR_SORT || nGlobalError)
|
|
|
|
{
|
|
|
|
SetError(errStackOverflow);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (rValCount == 0)
|
|
|
|
{
|
|
|
|
SetNoValue();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*ppSortArray = new double[rValCount];
|
2004-06-04 09:36:51 +00:00
|
|
|
double* pSortArray = *ppSortArray;
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!*ppSortArray)
|
|
|
|
{
|
|
|
|
rValCount = 0;
|
|
|
|
SetError(errStackOverflow);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sp = SaveSP;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nIndex = 0;
|
|
|
|
for (nParam = 0; nParam < nParamCount; nParam++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
2004-06-04 09:36:51 +00:00
|
|
|
pSortArray[nIndex] = GetDouble();
|
2000-09-18 23:16:46 +00:00
|
|
|
nIndex++;
|
|
|
|
break;
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
pSortArray[nIndex] = GetCellValue( aAdr, pCell );
|
2000-09-18 23:16:46 +00:00
|
|
|
nIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
USHORT nErr;
|
|
|
|
double nCellVal;
|
|
|
|
ScValueIterator aValIter(pDok, aRange);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
pSortArray[nIndex] = nCellVal;
|
2000-09-18 23:16:46 +00:00
|
|
|
nIndex++;
|
|
|
|
while (aValIter.GetNext(nCellVal, nErr))
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
pSortArray[nIndex] = nCellVal;
|
2000-09-18 23:16:46 +00:00
|
|
|
nIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nCount; i++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
pSortArray[nIndex] = pMat->GetDouble(i);
|
2001-04-27 21:44:26 +00:00
|
|
|
nIndex++;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nCount; i++)
|
2001-04-27 21:44:26 +00:00
|
|
|
if (!pMat->IsString(i))
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
pSortArray[nIndex] = pMat->GetDouble(i);
|
2000-09-18 23:16:46 +00:00
|
|
|
nIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default : SetError(errIllegalParameter); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBG_ASSERT(nIndex == rValCount,"nIndex != rValCount");
|
|
|
|
if (nGlobalError == 0)
|
|
|
|
{
|
|
|
|
double fVal;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nInd;
|
|
|
|
for (SCSIZE i = 0; (i + 4) <= rValCount-1; i += 4)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
nInd = rand() % (int) (rValCount-1);
|
2004-06-04 09:36:51 +00:00
|
|
|
fVal = pSortArray[i];
|
|
|
|
pSortArray[i] = pSortArray[nInd];
|
|
|
|
pSortArray[nInd] = fVal;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
QuickSort(0, static_cast<long>(rValCount)-1, pSortArray);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
nSize = rValCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::QuickSort(long nLo, long nHi, double* pSortArray)
|
|
|
|
{
|
|
|
|
if (nHi - nLo == 1)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
if (pSortArray[nLo] > pSortArray[nHi])
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
double fVal;
|
2004-06-04 09:36:51 +00:00
|
|
|
fVal = pSortArray[nLo];
|
|
|
|
pSortArray[nLo] = pSortArray[nHi];
|
|
|
|
pSortArray[nHi] = fVal;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
long ni = nLo;
|
|
|
|
long nj = nHi;
|
|
|
|
do
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
while (ni <= nHi && pSortArray[ni] < pSortArray[nLo]) ni++;
|
|
|
|
while (nj >= nLo && pSortArray[nLo] < pSortArray[nj]) nj--;
|
2000-09-18 23:16:46 +00:00
|
|
|
if (ni <= nj)
|
|
|
|
{
|
|
|
|
if (ni != nj)
|
|
|
|
{
|
|
|
|
double fVal;
|
2004-06-04 09:36:51 +00:00
|
|
|
fVal = pSortArray[ni];
|
|
|
|
pSortArray[ni] = pSortArray[nj];
|
|
|
|
pSortArray[nj] = fVal;
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
ni++;
|
|
|
|
nj--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (ni < nj);
|
|
|
|
if ((nj - nLo) < (nHi - ni))
|
|
|
|
{
|
|
|
|
if (nLo < nj) QuickSort(nLo, nj, pSortArray);
|
|
|
|
if (ni < nHi) QuickSort(ni, nHi, pSortArray);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ni < nHi) QuickSort(ni, nHi, pSortArray);
|
|
|
|
if (nLo < nj) QuickSort(nLo, nj, pSortArray);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScRank()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 2, 3 ) )
|
|
|
|
return;
|
|
|
|
BOOL bDescending;
|
|
|
|
if (nParamCount == 3)
|
|
|
|
bDescending = GetBool();
|
|
|
|
else
|
|
|
|
bDescending = FALSE;
|
|
|
|
double fCount = 1.0;
|
|
|
|
BOOL bValid = FALSE;
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
{
|
|
|
|
double x = GetDouble();
|
|
|
|
double fVal = GetDouble();
|
|
|
|
if (x == fVal)
|
|
|
|
bValid = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
ScAddress aAdr;
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
double fVal = GetDouble();
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
double x = GetCellValue( aAdr, pCell );
|
|
|
|
if (x == fVal)
|
|
|
|
bValid = TRUE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
ScRange aRange;
|
|
|
|
USHORT nErr = 0;
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
double fVal = GetDouble();
|
|
|
|
double nCellVal;
|
|
|
|
ScValueIterator aValIter(pDok, aRange, glSubTotal);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
if (nCellVal == fVal)
|
|
|
|
bValid = TRUE;
|
|
|
|
else if ((!bDescending && nCellVal > fVal) ||
|
|
|
|
(bDescending && nCellVal < fVal) )
|
|
|
|
fCount++;
|
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
if (nCellVal == fVal)
|
|
|
|
bValid = TRUE;
|
|
|
|
else if ((!bDescending && nCellVal > fVal) ||
|
|
|
|
(bDescending && nCellVal < fVal) )
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
double fVal = GetDouble();
|
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nCount; i++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
|
|
|
double x = pMat->GetDouble(i);
|
|
|
|
if (x == fVal)
|
|
|
|
bValid = TRUE;
|
|
|
|
else if ((!bDescending && x > fVal) ||
|
|
|
|
(bDescending && x < fVal) )
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nCount; i++)
|
2001-04-27 21:44:26 +00:00
|
|
|
if (!pMat->IsString(i))
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
2001-04-27 21:44:26 +00:00
|
|
|
double x = pMat->GetDouble(i);
|
2000-09-18 23:16:46 +00:00
|
|
|
if (x == fVal)
|
|
|
|
bValid = TRUE;
|
|
|
|
else if ((!bDescending && x > fVal) ||
|
2001-04-27 21:44:26 +00:00
|
|
|
(bDescending && x < fVal) )
|
2000-09-18 23:16:46 +00:00
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default : SetError(errIllegalParameter); break;
|
|
|
|
}
|
|
|
|
if (bValid)
|
|
|
|
PushDouble(fCount);
|
|
|
|
else
|
|
|
|
SetNoValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScAveDev()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCountMin( nParamCount, 1 ) )
|
|
|
|
return;
|
|
|
|
USHORT SaveSP = sp;
|
|
|
|
USHORT i;
|
|
|
|
double nMiddle = 0.0;
|
|
|
|
double rVal = 0.0;
|
|
|
|
double rValCount = 0.0;
|
|
|
|
ScAddress aAdr;
|
|
|
|
ScRange aRange;
|
|
|
|
for (i = 0; i < nParamCount; i++)
|
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
rVal += GetDouble();
|
|
|
|
rValCount++;
|
|
|
|
break;
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
{
|
|
|
|
rVal += GetCellValue( aAdr, pCell );
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
USHORT nErr = 0;
|
|
|
|
double nCellVal;
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
ScValueIterator aValIter(pDok, aRange);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
rVal += nCellVal;
|
|
|
|
rValCount++;
|
|
|
|
SetError(nErr);
|
|
|
|
while ((nErr == 0) && aValIter.GetNext(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
rVal += nCellVal;
|
|
|
|
rValCount++;
|
|
|
|
}
|
|
|
|
SetError(nErr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
rVal += pMat->GetDouble(nElem);
|
2001-04-27 21:44:26 +00:00
|
|
|
rValCount++;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
|
|
|
if (!pMat->IsString(nElem))
|
2001-04-27 21:44:26 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
rVal += pMat->GetDouble(nElem);
|
2001-04-27 21:44:26 +00:00
|
|
|
rValCount++;
|
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
SetError(errIllegalParameter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nGlobalError)
|
|
|
|
{
|
|
|
|
PushInt(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nMiddle = rVal / rValCount;
|
|
|
|
sp = SaveSP;
|
|
|
|
rVal = 0.0;
|
|
|
|
for (i = 0; i < nParamCount; i++)
|
|
|
|
{
|
|
|
|
switch (GetStackType())
|
|
|
|
{
|
|
|
|
case svDouble :
|
|
|
|
rVal += fabs(GetDouble() - nMiddle);
|
|
|
|
break;
|
|
|
|
case svSingleRef :
|
|
|
|
{
|
|
|
|
PopSingleRef( aAdr );
|
|
|
|
ScBaseCell* pCell = GetCell( aAdr );
|
|
|
|
if (HasCellValueData(pCell))
|
|
|
|
rVal += fabs(GetCellValue( aAdr, pCell ) - nMiddle);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svDoubleRef :
|
|
|
|
{
|
|
|
|
USHORT nErr = 0;
|
|
|
|
double nCellVal;
|
|
|
|
PopDoubleRef( aRange );
|
|
|
|
ScValueIterator aValIter(pDok, aRange);
|
|
|
|
if (aValIter.GetFirst(nCellVal, nErr))
|
|
|
|
{
|
|
|
|
rVal += (fabs(nCellVal - nMiddle));
|
|
|
|
while (aValIter.GetNext(nCellVal, nErr))
|
|
|
|
rVal += fabs(nCellVal - nMiddle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case svMatrix :
|
|
|
|
{
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat = PopMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat)
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount = pMat->GetElementCount();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (pMat->IsNumeric())
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
2004-03-08 10:48:19 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
|
2004-03-08 10:48:19 +00:00
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
for (SCSIZE nElem = 0; nElem < nCount; nElem++)
|
2004-03-08 10:48:19 +00:00
|
|
|
{
|
2007-02-27 11:16:29 +00:00
|
|
|
if (!pMat->IsString(nElem))
|
|
|
|
rVal += fabs(pMat->GetDouble(nElem) - nMiddle);
|
2004-03-08 10:48:19 +00:00
|
|
|
}
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default : SetError(errIllegalParameter); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PushDouble(rVal / rValCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScDevSq()
|
|
|
|
{
|
|
|
|
double nVal;
|
|
|
|
double nValCount;
|
|
|
|
GetStVarParams(nVal, nValCount);
|
|
|
|
PushDouble(nVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScProbability()
|
|
|
|
{
|
|
|
|
BYTE nParamCount = GetByte();
|
|
|
|
if ( !MustHaveParamCount( nParamCount, 3, 4 ) )
|
|
|
|
return;
|
|
|
|
double fUp, fLo;
|
|
|
|
fUp = GetDouble();
|
|
|
|
if (nParamCount == 4)
|
|
|
|
fLo = GetDouble();
|
|
|
|
else
|
|
|
|
fLo = fUp;
|
|
|
|
if (fLo > fUp)
|
|
|
|
{
|
|
|
|
double fTemp = fLo;
|
|
|
|
fLo = fUp;
|
|
|
|
fUp = fTemp;
|
|
|
|
}
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMatP = GetMatrix();
|
|
|
|
ScMatrixRef pMatW = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMatP || !pMatW)
|
|
|
|
SetIllegalParameter();
|
|
|
|
else
|
|
|
|
{
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMatP->GetDimensions(nC1, nR1);
|
|
|
|
pMatW->GetDimensions(nC2, nR2);
|
|
|
|
if (nC1 != nC2 || nR1 != nR2 || nC1 == 0 || nR1 == 0 ||
|
|
|
|
nC2 == 0 || nR2 == 0)
|
2007-07-06 11:35:41 +00:00
|
|
|
SetNA();
|
2000-09-18 23:16:46 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
double fSum = 0.0;
|
|
|
|
double fRes = 0.0;
|
|
|
|
BOOL bStop = FALSE;
|
|
|
|
double fP, fW;
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nCount1 = nC1 * nR1;
|
|
|
|
for ( SCSIZE i = 0; i < nCount1 && !bStop; i++ )
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (pMatP->IsValue(i) && pMatW->IsValue(i))
|
|
|
|
{
|
|
|
|
fP = pMatP->GetDouble(i);
|
|
|
|
fW = pMatW->GetDouble(i);
|
|
|
|
if (fP < 0.0 || fP > 1.0)
|
|
|
|
bStop = TRUE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fSum += fP;
|
|
|
|
if (fW >= fLo && fW <= fUp)
|
|
|
|
fRes += fP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2004-03-08 10:48:19 +00:00
|
|
|
SetError( errIllegalArgument);
|
2000-09-18 23:16:46 +00:00
|
|
|
}
|
|
|
|
if (bStop || fabs(fSum -1.0) > 1.0E-7)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble(fRes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScCorrel()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumSqrY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumSqrY += fValY * fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 2.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( (fSumXY-fSumX*fSumY/fCount)/
|
|
|
|
sqrt((fSumSqrX-fSumX*fSumX/fCount)*
|
|
|
|
(fSumSqrY-fSumY*fSumY/fCount)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScCovar()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 1.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( (fSumXY-fSumX*fSumY/fCount)/fCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScPearson()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumSqrY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumSqrY += fValY * fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 2.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( (fCount*fSumXY-fSumX*fSumY)/
|
|
|
|
sqrt((fCount*fSumSqrX-fSumX*fSumX)*
|
|
|
|
(fCount*fSumSqrY-fSumY*fSumY)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScRSQ()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumSqrY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumSqrY += fValY * fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 2.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( (fCount*fSumXY-fSumX*fSumY)*(fCount*fSumXY-fSumX*fSumY)/
|
|
|
|
(fCount*fSumSqrX-fSumX*fSumX)/(fCount*fSumSqrY-fSumY*fSumY));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScSTEXY()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumSqrY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumSqrY += fValY * fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 3.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble(sqrt((fCount*fSumSqrY - fSumY*fSumY -
|
|
|
|
(fCount*fSumXY -fSumX*fSumY)*(fCount*fSumXY -fSumX*fSumY)/
|
|
|
|
(fCount*fSumSqrX-fSumX*fSumX) )/(fCount*(fCount-2.0))));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScSlope()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 1.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( (fCount*fSumXY-fSumX*fSumY)/
|
|
|
|
(fCount*fSumSqrX-fSumX*fSumX) );
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScIntercept()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 2 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 1.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( fSumY/fCount - (fCount*fSumXY-fSumX*fSumY)/
|
|
|
|
(fCount*fSumSqrX-fSumX*fSumX)*fSumX/fCount );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScInterpreter::ScForecast()
|
|
|
|
{
|
|
|
|
if ( !MustHaveParamCount( GetByte(), 3 ) )
|
|
|
|
return;
|
2004-03-08 10:48:19 +00:00
|
|
|
ScMatrixRef pMat1 = GetMatrix();
|
|
|
|
ScMatrixRef pMat2 = GetMatrix();
|
2000-09-18 23:16:46 +00:00
|
|
|
if (!pMat1 || !pMat2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
2004-06-04 09:36:51 +00:00
|
|
|
SCSIZE nC1, nC2;
|
|
|
|
SCSIZE nR1, nR2;
|
2000-09-18 23:16:46 +00:00
|
|
|
pMat1->GetDimensions(nC1, nR1);
|
|
|
|
pMat2->GetDimensions(nC2, nR2);
|
|
|
|
if (nR1 != nR2 || nC1 != nC2)
|
|
|
|
{
|
|
|
|
SetIllegalParameter();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
double fVal = GetDouble();
|
|
|
|
double fCount = 0.0;
|
|
|
|
double fSumX = 0.0;
|
|
|
|
double fSumSqrX = 0.0;
|
|
|
|
double fSumY = 0.0;
|
|
|
|
double fSumXY = 0.0;
|
|
|
|
double fValX, fValY;
|
2004-06-04 09:36:51 +00:00
|
|
|
for (SCSIZE i = 0; i < nC1; i++)
|
|
|
|
for (SCSIZE j = 0; j < nR1; j++)
|
2000-09-18 23:16:46 +00:00
|
|
|
{
|
|
|
|
if (!pMat1->IsString(i,j) && !pMat2->IsString(i,j))
|
|
|
|
{
|
|
|
|
fValX = pMat1->GetDouble(i,j);
|
|
|
|
fValY = pMat2->GetDouble(i,j);
|
|
|
|
fSumX += fValX;
|
|
|
|
fSumSqrX += fValX * fValX;
|
|
|
|
fSumY += fValY;
|
|
|
|
fSumXY += fValX*fValY;
|
|
|
|
fCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fCount < 1.0)
|
|
|
|
SetNoValue();
|
|
|
|
else
|
|
|
|
PushDouble( fSumY/fCount + (fCount*fSumXY-fSumX*fSumY)/
|
|
|
|
(fCount*fSumSqrX-fSumX*fSumX) * (fVal - fSumX/fCount) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|