View | Details | Raw Unified | Return to issue 32833
Collapse All | Expand All

(-)inc/interpre.hxx (+2 lines)
Lines 612-617 Link Here
612
double taylor(double* pPolynom, USHORT nMax, double x);
612
double taylor(double* pPolynom, USHORT nMax, double x);
613
double gauss(double x);
613
double gauss(double x);
614
double gaussinv(double x);
614
double gaussinv(double x);
615
double normsdist(double x);
616
double normsinv(double x);
615
double GetGammaDist(double x, double alpha, double beta);
617
double GetGammaDist(double x, double alpha, double beta);
616
double GetBetaDist(double x, double alpha, double beta);
618
double GetBetaDist(double x, double alpha, double beta);
617
double GetChiDist(double fChi, double fDF);
619
double GetChiDist(double fChi, double fDF);
(-)tool/interpr3.cxx (-24 / +95 lines)
Lines 59-70 Link Here
59
 *
59
 *
60
 ************************************************************************/
60
 ************************************************************************/
61
61
62
#ifdef PCH
63
#include "core_pch.hxx"
64
#endif
65
66
#pragma hdrstop
67
68
// INCLUDE ---------------------------------------------------------------
62
// INCLUDE ---------------------------------------------------------------
69
63
70
#include <tools/solar.h>
64
#include <tools/solar.h>
Lines 283-288 Link Here
283
#pragma optimize("",on)
277
#pragma optimize("",on)
284
#endif
278
#endif
285
279
280
281
double ScInterpreter::normsdist(double x)
282
{
283
	return 0.5 + gauss(x);
284
}
285
286
287
double ScInterpreter::normsinv(double x)
288
{
289
    double y;
290
	if (x < 0.0 || x > 1.0)
291
    {
292
	    SetError(errIllegalArgument);
293
        y = 0.0;
294
    }
295
	else if (x == 0.0 || x == 1.0)
296
    {
297
        SetError(errNoValue);
298
        y = 0.0;
299
    }
300
	else
301
    {
302
        // Algorithm of #i32833#
303
        //
304
        // We have
305
        // normsdist(-5.99) =~= 0,000000001049
306
        // normsdist(5,99)  =~= 0,999999998951
307
308
        /* Outside the external borders of our searching segment, we use the
309
         * old method. We know the result will be with an accuracy better than
310
         * 1.10E-8. Inside, we use the new approach.
311
         */
312
        if (x <= 0.000000001049 || x >= 0.999999998951)
313
		    y = gaussinv(x);
314
        else
315
        {
316
            const double fEps = 1.10E-12;
317
            // set the searching segment
318
            double fMin = -5.99;
319
            double fMax =  5.99;
320
            double fMid;
321
            do
322
            {
323
                fMid = (fMin + fMax) / 2;
324
                double my_y = normsdist( fMid);
325
                if (::rtl::math::approxEqual( x, my_y))
326
                {
327
                    // jackpot, we're lucky, stop the algorithm
328
                    // y = fMid;   is done below after the loop
329
                    break;  // while
330
                }
331
                else
332
                {
333
                    if (x < my_y )
334
                        fMax = fMid;
335
                    else
336
                        fMin = fMid;
337
                }
338
            } while (fabs( fMin - fMax) > fEps);
339
340
            /* End of loop --> we know that  y  is in the segment
341
             * [ y - fMin-fEps, y + fMin-fEps] (with our definition of
342
             * the normal standard law normsdist, not the real law). It means
343
             * that we're sure that normsdist(norminv(x)) and x have the same 7
344
             * decimals, and probably more.
345
             */
346
            y = fMid;
347
        }
348
    }
349
	return y;
350
}
351
352
286
double ScInterpreter::Fakultaet(double x)
353
double ScInterpreter::Fakultaet(double x)
287
{
354
{
288
	x = ::rtl::math::approxFloor(x);
355
	x = ::rtl::math::approxFloor(x);
Lines 975-981 Link Here
975
1042
976
void ScInterpreter::ScStdNormDist()
1043
void ScInterpreter::ScStdNormDist()
977
{
1044
{
978
	PushDouble(0.5 + gauss(GetDouble()));
1045
	PushDouble( normsdist( GetDouble()));
979
}
1046
}
980
1047
981
void ScInterpreter::ScExpDist()
1048
void ScInterpreter::ScExpDist()
Lines 1180-1216 Link Here
1180
		double sigma = GetDouble();
1247
		double sigma = GetDouble();
1181
		double mue   = GetDouble();
1248
		double mue   = GetDouble();
1182
		double x     = GetDouble();
1249
		double x     = GetDouble();
1183
		if (sigma <= 0.0 || x < 0.0 || x > 1.0)
1250
		if (sigma <= 0.0)
1184
			SetIllegalArgument();
1251
			SetIllegalArgument();
1185
		else if (x == 0.0 || x == 1.0)
1186
			SetNoValue();
1187
		else
1252
		else
1188
			PushDouble(gaussinv(x)*sigma + mue);
1253
        {
1254
            double y = normsinv(x);
1255
            if (nGlobalError)
1256
                PushInt(0);
1257
            else
1258
                PushDouble( y * sigma + mue);
1259
        }
1189
	}
1260
	}
1190
}
1261
}
1191
1262
1192
void ScInterpreter::ScSNormInv()
1263
void ScInterpreter::ScSNormInv()
1193
{
1264
{
1194
	double x = GetDouble();
1265
    PushDouble( normsinv( GetDouble()));
1195
	if (x < 0.0 || x > 1.0)
1196
		SetIllegalArgument();
1197
	else if (x == 0.0 || x == 1.0)
1198
		SetNoValue();
1199
	else
1200
		PushDouble(gaussinv(x));
1201
}
1266
}
1202
1267
1203
void ScInterpreter::ScLogNormInv()
1268
void ScInterpreter::ScLogNormInv()
1204
{
1269
{
1205
	if ( MustHaveParamCount( GetByte(), 3 ) )
1270
	if ( MustHaveParamCount( GetByte(), 3 ) )
1206
	{
1271
	{
1207
		double sigma = GetDouble();					// Stdabw
1272
		double sigma = GetDouble();
1208
		double mue = GetDouble();					// Mittelwert
1273
		double mue = GetDouble();
1209
		double y = GetDouble();						// y
1274
		double x = GetDouble();
1210
		if (sigma <= 0.0 || y <= 0.0 || y >= 1.0)
1275
		if (sigma <= 0.0)
1211
			SetIllegalArgument();
1276
			SetIllegalArgument();
1212
		else
1277
		else
1213
			PushDouble(exp(mue+sigma*gaussinv(y)));
1278
        {
1279
            double y = normsinv(x);
1280
            if (nGlobalError)
1281
                PushInt(0);
1282
            else
1283
                PushDouble( exp( y * sigma + mue));
1284
        }
1214
	}
1285
	}
1215
}
1286
}
1216
1287
Lines 1417-1423 Link Here
1417
		if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
1488
		if (sigma <= 0.0 || alpha <= 0.0 || alpha >= 1.0 || n < 1.0)
1418
			SetIllegalArgument();
1489
			SetIllegalArgument();
1419
		else
1490
		else
1420
			PushDouble( gaussinv(1.0-alpha/2.0) * sigma/sqrt(n) );
1491
			PushDouble( normsinv(1.0-alpha/2.0) * sigma/sqrt(n) );
1421
	}
1492
	}
1422
}
1493
}
1423
1494

Return to issue 32833