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 |
|