Lines 949-965
Link Here
|
949 |
const double fLogDblMin = log( ::std::numeric_limits<double>::min()); |
949 |
const double fLogDblMin = log( ::std::numeric_limits<double>::min()); |
950 |
double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5); |
950 |
double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5); |
951 |
double fLogX = log(fX); |
951 |
double fLogX = log(fX); |
952 |
double fAm1 = fA-1.0; |
952 |
double fAm1LogX = (fA-1.0) * fLogX; |
953 |
double fBm1 = fB-1.0; |
953 |
double fBm1LogY = (fB-1.0) * fLogY; |
954 |
double fLogBeta = GetLogBeta(fA,fB); |
954 |
double fLogBeta = GetLogBeta(fA,fB); |
955 |
// check whether parts over- or underflow |
955 |
// check whether parts over- or underflow |
956 |
if ( fAm1 * fLogX < fLogDblMax && fAm1 * fLogX > fLogDblMin |
956 |
if ( fAm1LogX < fLogDblMax && fAm1LogX > fLogDblMin |
957 |
&& fBm1 * fLogY < fLogDblMax && fBm1* fLogY > fLogDblMin |
957 |
&& fBm1LogY < fLogDblMax && fBm1LogY > fLogDblMin |
958 |
&& fLogBeta < fLogDblMax && fLogBeta > fLogDblMin ) |
958 |
&& fLogBeta < fLogDblMax && fLogBeta > fLogDblMin |
|
|
959 |
&& fAm1LogX + fBm1LogY < fLogDblMax && fAm1LogX + fBm1LogY > fLogDblMin) |
959 |
return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB); |
960 |
return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB); |
960 |
else // need logarithm; |
961 |
else // need logarithm; |
961 |
// might overflow as a whole, but seldom, not worth to pre-detect it |
962 |
// might overflow as a whole, but seldom, not worth to pre-detect it |
962 |
return exp((fA-1.0)*fLogX + (fB-1.0)* fLogY - fLogBeta); |
963 |
return exp( fAm1LogX + fBm1LogY - fLogBeta); |
963 |
} |
964 |
} |
964 |
|
965 |
|
965 |
|
966 |
|
Lines 1226-1346
Link Here
|
1226 |
} |
1227 |
} |
1227 |
} |
1228 |
} |
1228 |
|
1229 |
|
1229 |
void ScInterpreter::ScB() |
1230 |
|
1230 |
{ |
1231 |
double ScInterpreter::GetBinomDistPMF(double x, double n, double p) |
1231 |
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScB" ); |
1232 |
// used in ScB and ScBinomDist |
1232 |
sal_uInt8 nParamCount = GetByte(); |
1233 |
// preconditions: 0.0 <= x <= n, 0.0 < p < 1.0; x,n integral although double |
1233 |
if ( !MustHaveParamCount( nParamCount, 3, 4 ) ) |
|
|
1234 |
return ; |
1235 |
if (nParamCount == 3) |
1236 |
{ |
1237 |
double x = ::rtl::math::approxFloor(GetDouble()); |
1238 |
double p = GetDouble(); |
1239 |
double n = ::rtl::math::approxFloor(GetDouble()); |
1240 |
if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) |
1241 |
PushIllegalArgument(); |
1242 |
else |
1243 |
{ |
1234 |
{ |
1244 |
double q = 1.0 - p; |
1235 |
double q = (0.5 - p) + 0.5; |
1245 |
double fFactor = pow(q, n); |
1236 |
double fFactor = pow(q, n); |
1246 |
if (fFactor == 0.0) |
1237 |
if (fFactor <=::std::numeric_limits<double>::min()) |
1247 |
{ |
1238 |
{ |
1248 |
fFactor = pow(p, n); |
1239 |
fFactor = pow(p, n); |
1249 |
if (fFactor == 0.0) |
1240 |
if (fFactor <= ::std::numeric_limits<double>::min()) |
1250 |
PushNoValue(); |
1241 |
return GetBetaDistPDF(p, x+1.0, n-x+1.0)/(n+1.0); |
1251 |
else |
1242 |
else |
1252 |
{ |
1243 |
{ |
1253 |
sal_uLong max = (sal_uLong) (n - x); |
1244 |
sal_uInt32 max = static_cast<sal_uInt32>(n - x); |
1254 |
for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) |
1245 |
for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++) |
1255 |
fFactor *= (n-i)/(i+1)*q/p; |
1246 |
fFactor *= (n-i)/(i+1)*q/p; |
1256 |
PushDouble(fFactor); |
1247 |
return fFactor; |
1257 |
} |
1248 |
} |
1258 |
} |
1249 |
} |
1259 |
else |
1250 |
else |
1260 |
{ |
1251 |
{ |
1261 |
sal_uLong max = (sal_uLong) x; |
1252 |
sal_uInt32 max = static_cast<sal_uInt32>(x); |
1262 |
for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) |
1253 |
for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++) |
1263 |
fFactor *= (n-i)/(i+1)*p/q; |
1254 |
fFactor *= (n-i)/(i+1)*p/q; |
1264 |
PushDouble(fFactor); |
1255 |
return fFactor; |
1265 |
} |
|
|
1266 |
} |
1256 |
} |
1267 |
} |
1257 |
} |
1268 |
else if (nParamCount == 4) |
1258 |
|
1269 |
{ |
1259 |
double lcl_GetBinomDistRange(double n, double xs,double xe, |
1270 |
double xe = GetDouble(); |
1260 |
double fFactor /* q^n */, double p, double q) |
1271 |
double xs = GetDouble(); |
1261 |
//preconditions: 0.0 <= xs < xe <= n; xs,xe,n integral although double |
1272 |
double p = GetDouble(); |
|
|
1273 |
double n = GetDouble(); |
1274 |
// alter Stand 300-SC |
1275 |
// if ((xs < n) && (xe < n) && (p < 1.0)) |
1276 |
// { |
1277 |
// double Varianz = sqrt(n * p * (1.0 - p)); |
1278 |
// xs = fabs(xs - (n * p /* / 2.0 STE */ )); |
1279 |
// xe = fabs(xe - (n * p /* / 2.0 STE */ )); |
1280 |
//// STE double nVal = gauss((xs + 0.5) / Varianz) + gauss((xe + 0.5) / Varianz); |
1281 |
// double nVal = fabs(gauss(xs / Varianz) - gauss(xe / Varianz)); |
1282 |
// PushDouble(nVal); |
1283 |
// } |
1284 |
bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n); |
1285 |
if ( bIsValidX && 0.0 < p && p < 1.0 ) |
1286 |
{ |
1287 |
double q = 1.0 - p; |
1288 |
double fFactor = pow(q, n); |
1289 |
if (fFactor == 0.0) |
1290 |
{ |
1291 |
fFactor = pow(p, n); |
1292 |
if (fFactor == 0.0) |
1293 |
PushNoValue(); |
1294 |
else |
1295 |
{ |
1262 |
{ |
1296 |
double fSum = 0.0; |
1263 |
sal_uInt32 i; |
1297 |
sal_uLong max; |
1264 |
double fSum; |
1298 |
if (xe < (sal_uLong) n) |
1265 |
// skip summands index 0 to xs-1, start sum with index xs |
1299 |
max = (sal_uLong) (n-xe)-1; |
1266 |
sal_uInt32 nXs = static_cast<sal_uInt32>( xs ); |
1300 |
else |
1267 |
for (i = 1; i <= nXs && fFactor > 0.0; i++) |
1301 |
max = 0; |
1268 |
fFactor *= (n-i+1)/i * p/q; |
1302 |
sal_uLong i; |
1269 |
fSum = fFactor; // Summand xs |
1303 |
for (i = 0; i < max && fFactor > 0.0; i++) |
1270 |
sal_uInt32 nXe = static_cast<sal_uInt32>(xe); |
1304 |
fFactor *= (n-i)/(i+1)*q/p; |
1271 |
for (i = nXs+1; i <= nXe && fFactor > 0.0; i++) |
1305 |
if (xs < (sal_uLong) n) |
|
|
1306 |
max = (sal_uLong) (n-xs); |
1307 |
else |
1308 |
fSum = fFactor; |
1309 |
for (; i < max && fFactor > 0.0; i++) |
1310 |
{ |
1272 |
{ |
1311 |
fFactor *= (n-i)/(i+1)*q/p; |
1273 |
fFactor *= (n-i+1)/i * p/q; |
1312 |
fSum += fFactor; |
1274 |
fSum += fFactor; |
1313 |
} |
1275 |
} |
1314 |
PushDouble(fSum); |
1276 |
return (fSum>1.0) ? 1.0 : fSum; |
1315 |
} |
1277 |
} |
|
|
1278 |
|
1279 |
void ScInterpreter::ScB() |
1280 |
{ |
1281 |
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScB" ); |
1282 |
sal_uInt8 nParamCount = GetByte(); |
1283 |
if ( !MustHaveParamCount( nParamCount, 3, 4 ) ) |
1284 |
return ; |
1285 |
if (nParamCount == 3) // mass function |
1286 |
{ |
1287 |
double x = ::rtl::math::approxFloor(GetDouble()); |
1288 |
double p = GetDouble(); |
1289 |
double n = ::rtl::math::approxFloor(GetDouble()); |
1290 |
if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) |
1291 |
PushIllegalArgument(); |
1292 |
else |
1293 |
if (p == 0.0) |
1294 |
PushDouble( (x == 0.0) ? 1.0 : 0.0 ); |
1295 |
else |
1296 |
if ( p == 1.0) |
1297 |
PushDouble( (x == n) ? 1.0 : 0.0); |
1298 |
else |
1299 |
PushDouble(GetBinomDistPMF(x,n,p)); |
1316 |
} |
1300 |
} |
1317 |
else |
1301 |
else |
|
|
1302 |
{ // nParamCount == 4 |
1303 |
double xe = ::rtl::math::approxFloor(GetDouble()); |
1304 |
double xs = ::rtl::math::approxFloor(GetDouble()); |
1305 |
double p = GetDouble(); |
1306 |
double n = ::rtl::math::approxFloor(GetDouble()); |
1307 |
double q = (0.5 - p) + 0.5; |
1308 |
bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n); |
1309 |
if ( bIsValidX && 0.0 < p && p < 1.0) |
1318 |
{ |
1310 |
{ |
1319 |
sal_uLong max; |
1311 |
if (xs == xe) // mass function |
1320 |
double fSum; |
1312 |
PushDouble(GetBinomDistPMF(xs,n,p)); |
1321 |
if ( (sal_uLong) xs == 0) |
1313 |
else |
1322 |
{ |
1314 |
{ |
1323 |
fSum = fFactor; |
1315 |
double fFactor = pow(q, n); |
1324 |
max = 0; |
1316 |
if (fFactor > ::std::numeric_limits<double>::min()) |
1325 |
} |
1317 |
PushDouble(lcl_GetBinomDistRange(n,xs,xe,fFactor,p,q)); |
1326 |
else |
1318 |
else |
1327 |
{ |
1319 |
{ |
1328 |
max = (sal_uLong) xs-1; |
1320 |
fFactor = pow(p, n); |
1329 |
fSum = 0.0; |
1321 |
if (fFactor > ::std::numeric_limits<double>::min()) |
|
|
1322 |
{ |
1323 |
// sum from j=xs to xe {(n choose j) * p^j * q^(n-j)} |
1324 |
// = sum from i = n-xe to n-xs { (n choose i) * q^i * p^(n-i)} |
1325 |
PushDouble(lcl_GetBinomDistRange(n,n-xe,n-xs,fFactor,q,p)); |
1330 |
} |
1326 |
} |
1331 |
sal_uLong i; |
|
|
1332 |
for (i = 0; i < max && fFactor > 0.0; i++) |
1333 |
fFactor *= (n-i)/(i+1)*p/q; |
1334 |
if ((sal_uLong)xe == 0) // beide 0 |
1335 |
fSum = fFactor; |
1336 |
else |
1327 |
else |
1337 |
max = (sal_uLong) xe; |
1328 |
PushDouble(GetBetaDist(q,n-xe,xe+1.0)-GetBetaDist(q,n-xs+1,xs) ); |
1338 |
for (; i < max && fFactor > 0.0; i++) |
|
|
1339 |
{ |
1340 |
fFactor *= (n-i)/(i+1)*p/q; |
1341 |
fSum += fFactor; |
1342 |
} |
1329 |
} |
1343 |
PushDouble(fSum); |
|
|
1344 |
} |
1330 |
} |
1345 |
} |
1331 |
} |
1346 |
else |
1332 |
else |
Lines 1365-1441
Link Here
|
1365 |
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBinomDist" ); |
1351 |
RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBinomDist" ); |
1366 |
if ( MustHaveParamCount( GetByte(), 4 ) ) |
1352 |
if ( MustHaveParamCount( GetByte(), 4 ) ) |
1367 |
{ |
1353 |
{ |
1368 |
double kum = GetDouble(); // 0 oder 1 |
1354 |
bool bIsCum = GetBool(); // false=mass function; true=cumulative |
1369 |
double p = GetDouble(); // p |
1355 |
double p = GetDouble(); |
1370 |
double n = ::rtl::math::approxFloor(GetDouble()); // n |
1356 |
double n = ::rtl::math::approxFloor(GetDouble()); |
1371 |
double x = ::rtl::math::approxFloor(GetDouble()); // x |
1357 |
double x = ::rtl::math::approxFloor(GetDouble()); |
1372 |
double fFactor, q, fSum; |
1358 |
double q = (0.5 - p) + 0.5; // get one bit more for p near 1.0 |
|
|
1359 |
double fFactor, fSum; |
1373 |
if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) |
1360 |
if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) |
1374 |
PushIllegalArgument(); |
|
|
1375 |
else if (kum == 0.0) // Dichte |
1376 |
{ |
1361 |
{ |
1377 |
q = 1.0 - p; |
1362 |
PushIllegalArgument(); |
1378 |
fFactor = pow(q, n); |
1363 |
return; |
1379 |
if (fFactor == 0.0) |
|
|
1380 |
{ |
1381 |
fFactor = pow(p, n); |
1382 |
if (fFactor == 0.0) |
1383 |
PushNoValue(); |
1384 |
else |
1385 |
{ |
1386 |
sal_uLong max = (sal_uLong) (n - x); |
1387 |
for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) |
1388 |
fFactor *= (n-i)/(i+1)*q/p; |
1389 |
PushDouble(fFactor); |
1390 |
} |
1391 |
} |
1364 |
} |
1392 |
else |
1365 |
if ( p == 0.0) |
1393 |
{ |
1366 |
{ |
1394 |
sal_uLong max = (sal_uLong) x; |
1367 |
PushDouble( (x==0.0 || bIsCum) ? 1.0 : 0.0 ); |
1395 |
for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) |
1368 |
return; |
1396 |
fFactor *= (n-i)/(i+1)*p/q; |
|
|
1397 |
PushDouble(fFactor); |
1398 |
} |
1369 |
} |
|
|
1370 |
if ( p == 1.0) |
1371 |
{ |
1372 |
PushDouble( (x==n) ? 1.0 : 0.0); |
1373 |
return; |
1399 |
} |
1374 |
} |
1400 |
else // Verteilung |
1375 |
if (!bIsCum) |
|
|
1376 |
PushDouble( GetBinomDistPMF(x,n,p)); |
1377 |
else |
1401 |
{ |
1378 |
{ |
1402 |
if (n == x) |
1379 |
if (x == n) |
1403 |
PushDouble(1.0); |
1380 |
PushDouble(1.0); |
1404 |
else |
1381 |
else |
1405 |
{ |
1382 |
{ |
1406 |
q = 1.0 - p; |
|
|
1407 |
fFactor = pow(q, n); |
1383 |
fFactor = pow(q, n); |
1408 |
if (fFactor == 0.0) |
1384 |
if (x == 0.0) |
|
|
1385 |
PushDouble(fFactor); |
1386 |
else |
1387 |
if (fFactor <= ::std::numeric_limits<double>::min()) |
1409 |
{ |
1388 |
{ |
1410 |
fFactor = pow(p, n); |
1389 |
fFactor = pow(p, n); |
1411 |
if (fFactor == 0.0) |
1390 |
if (fFactor <= ::std::numeric_limits<double>::min()) |
1412 |
PushNoValue(); |
1391 |
PushDouble(GetBetaDist(q,n-x,x+1.0)); |
1413 |
else |
1392 |
else |
1414 |
{ |
1393 |
{ |
|
|
1394 |
if (fFactor > fMachEps) |
1395 |
{ |
1415 |
fSum = 1.0 - fFactor; |
1396 |
fSum = 1.0 - fFactor; |
1416 |
sal_uLong max = (sal_uLong) (n - x) - 1; |
1397 |
sal_uInt32 max = static_cast<sal_uInt32> (n - x) - 1; |
1417 |
for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) |
1398 |
for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++) |
1418 |
{ |
1399 |
{ |
1419 |
fFactor *= (n-i)/(i+1)*q/p; |
1400 |
fFactor *= (n-i)/(i+1)*q/p; |
1420 |
fSum -= fFactor; |
1401 |
fSum -= fFactor; |
1421 |
} |
1402 |
} |
1422 |
if (fSum < 0.0) |
1403 |
PushDouble( (fSum < 0.0) ? 0.0 : fSum ); |
1423 |
PushDouble(0.0); |
|
|
1424 |
else |
1425 |
PushDouble(fSum); |
1426 |
} |
1427 |
} |
1404 |
} |
1428 |
else |
1405 |
else |
1429 |
{ |
1406 |
PushDouble(lcl_GetBinomDistRange(n,n-x,n,fFactor,q,p)); |
1430 |
fSum = fFactor; |
|
|
1431 |
sal_uLong max = (sal_uLong) x; |
1432 |
for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) |
1433 |
{ |
1434 |
fFactor *= (n-i)/(i+1)*p/q; |
1435 |
fSum += fFactor; |
1436 |
} |
1407 |
} |
1437 |
PushDouble(fSum); |
|
|
1438 |
} |
1408 |
} |
|
|
1409 |
else |
1410 |
PushDouble( lcl_GetBinomDistRange(n,0.0,x,fFactor,p,q)) ; |
1439 |
} |
1411 |
} |
1440 |
} |
1412 |
} |
1441 |
} |
1413 |
} |