Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

490 lines
16 KiB

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
statfuns.c
Abstract:
Statistical calculation functions
--*/
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#include <pdh.h>
#include "pdhicalc.h"
#include "pdhitype.h"
#include "pdhmsg.h"
#define PDHI_FMT_FILTER (PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE)
PDH_STATUS
APIENTRY
PdhiComputeFirstLastStats (
IN PPDHI_COUNTER pCounter,
IN DWORD dwFormat,
IN DWORD dwFirstEntry,
IN DWORD dwNumEntries,
IN PPDH_RAW_COUNTER lpRawValueArray,
IN PPDH_STATISTICS data
)
{
DOUBLE dThisValue = (double)0.0;
DOUBLE dMin = (double)+10E8; // these are just "big" seed numbers
DOUBLE dMax = (double)-10E8;
DOUBLE dMean = (double)0.0;
BOOLEAN bFirstItem = TRUE;
DWORD dwItem;
DWORD dwValidItemCount = 0;
DWORD dwFirstValidItem = 0;
DWORD dwLastValidItem = 0;
DWORD dwComputeFormat;
PPDH_RAW_COUNTER pNewCounter;
PPDH_RAW_COUNTER pOldCounter;
PDH_FMT_COUNTERVALUE fmtValue;
DWORD cStatusReturn;
__try {
// initialize th user's data buffer
data->dwFormat = 0;
data->count = 0;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
data->min.largeValue = 0;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
data->max.largeValue = 0;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
data->mean.largeValue = 0;
// find first valid counter in array
dwItem = dwFirstEntry;
pNewCounter = NULL;
pOldCounter = &lpRawValueArray[dwItem];
do {
// get value of this instance if next counter is valid
if ((pOldCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
(pOldCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
pNewCounter = pOldCounter;
dwFirstValidItem = dwItem;
break;
} else {
dwItem = ++dwItem % dwNumEntries;
pOldCounter = &lpRawValueArray[dwItem];
}
} while (dwItem != dwFirstEntry);
// do calculations in Floating point format
dwComputeFormat = dwFormat;
dwComputeFormat &= ~PDHI_FMT_FILTER;
dwComputeFormat |= PDH_FMT_DOUBLE | PDH_FMT_NOCAP100;
// go to next entry to begin processing
dwItem = ++dwItem % dwNumEntries;
pNewCounter = &lpRawValueArray[dwItem];
// these counters need 2 or more entrys to compute values from
if ((dwItem != dwFirstEntry) && (dwNumEntries > 1)) {
// start record found so initialize and continue
dwLastValidItem = dwItem;
// step through the remaining entries
while (dwItem != dwFirstEntry) {
// get value of this instance if next counter is valid
if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
(pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
// record this as a valid counter
dwLastValidItem = dwItem;
// get current value
cStatusReturn = PdhiComputeFormattedValue (
pCounter->CalcFunc,
pCounter->plCounterInfo.dwCounterType,
pCounter->lScale,
dwComputeFormat,
pNewCounter,
pOldCounter,
& pCounter->TimeBase,
0L,
& fmtValue);
if (cStatusReturn == ERROR_SUCCESS) {
dThisValue = fmtValue.doubleValue;
// update min & max
if (bFirstItem) {
dMax = dMin = dThisValue;
bFirstItem = FALSE;
}
else {
if (dThisValue > dMax) dMax = dThisValue;
if (dThisValue < dMin) dMin = dThisValue;
}
dwValidItemCount++;
}
}
pOldCounter = pNewCounter;
dwItem = ++dwItem % dwNumEntries;
pNewCounter = &lpRawValueArray[dwItem];
}
// compute average
if (dwValidItemCount > 0) {
pOldCounter = &lpRawValueArray[dwFirstValidItem];
pNewCounter = &lpRawValueArray[dwLastValidItem];
cStatusReturn = PdhiComputeFormattedValue (
pCounter->CalcFunc,
pCounter->plCounterInfo.dwCounterType,
pCounter->lScale,
dwComputeFormat,
pNewCounter,
pOldCounter,
&pCounter->TimeBase,
0L,
&fmtValue);
if (cStatusReturn == ERROR_SUCCESS) {
dMean = fmtValue.doubleValue;
cStatusReturn = PDH_CSTATUS_VALID_DATA;
}
else {
dMean = 0.0;
}
} else {
dMean = 0.0;
dMax = 0.0;
dMin = 0.0;
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
}
} else {
// array does not contain a valid counter so exit
dMean = 0.0;
dMax = 0.0;
dMin = 0.0;
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
}
// update user's buffer with new data
data->dwFormat = dwFormat;
data->count = dwValidItemCount;
data->min.CStatus = cStatusReturn;
data->max.CStatus = cStatusReturn;
data->mean.CStatus = cStatusReturn;
switch ((dwFormat & PDHI_FMT_FILTER)) {
case PDH_FMT_LONG:
if (dMin > (DOUBLE) MAXLONG) {
data->min.longValue = MAXLONG;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->min.longValue = (long) dMin;
}
if (dMax > (DOUBLE) MAXLONG) {
data->max.longValue = MAXLONG;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->max.longValue = (long) dMax;
}
if (dMean > (DOUBLE) MAXLONG) {
data->mean.longValue = MAXLONG;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->mean.longValue = (long) dMean;
}
break;
case PDH_FMT_DOUBLE:
data->min.doubleValue = dMin;
data->max.doubleValue = dMax;
data->mean.doubleValue = dMean;
break;
case PDH_FMT_LARGE:
default:
if (dMin > (DOUBLE) MAXLONGLONG) {
data->min.largeValue = MAXLONGLONG;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->min.largeValue = (LONGLONG) dMin;
}
if (dMax > (DOUBLE) MAXLONGLONG) {
data->max.largeValue = MAXLONGLONG;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->max.largeValue = (LONGLONG) dMax;
}
if (dMean > (DOUBLE) MAXLONGLONG) {
data->mean.largeValue = MAXLONGLONG;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->mean.largeValue = (LONGLONG) dMean;
}
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
return PDH_INVALID_ARGUMENT;
}
return ERROR_SUCCESS;
}
PDH_STATUS
APIENTRY
PdhiComputeRawCountStats (
IN PPDHI_COUNTER pCounter,
IN DWORD dwFormat,
IN DWORD dwFirstEntry,
IN DWORD dwNumEntries,
IN PPDH_RAW_COUNTER lpRawValueArray,
IN PPDH_STATISTICS data
)
{
DOUBLE dThisValue = (double)0.0;
DOUBLE dMin = (double)+10E8; // these are just "big" seed numbers
DOUBLE dMax = (double)-10E8;
DOUBLE dMean = (double)0.0;
BOOLEAN bFirstItem = TRUE;
DOUBLE dScale;
DWORD dwItem;
DWORD dwValidItemCount = 0;
DWORD dwFirstValidItem = 0;
DWORD dwLastValidItem = 0;
DWORD dwComputeFormat;
PPDH_RAW_COUNTER pNewCounter;
PPDH_RAW_COUNTER pOldCounter = NULL;
PDH_FMT_COUNTERVALUE fmtValue;
DWORD cStatusReturn;
UNREFERENCED_PARAMETER (dwFirstEntry);
__try {
// initialize the user's data buffer
data->dwFormat = 0;
data->count = 0;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
data->min.largeValue = 0;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
data->max.largeValue = 0;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
data->mean.largeValue = 0;
// find first valid counter in array
dwItem = 0;
pNewCounter = lpRawValueArray;
while (dwItem < dwNumEntries) {
// get value of this instance if next counter is valid
if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
(pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
break;
} else {
pOldCounter = pNewCounter;
pNewCounter++;
dwItem++;
}
}
// do calculations in Floating point format
dwComputeFormat = dwFormat;
dwComputeFormat &= ~PDHI_FMT_FILTER;
dwComputeFormat |= PDH_FMT_DOUBLE | PDH_FMT_NOCAP100;
if ((dwItem != dwNumEntries) && (dwNumEntries > 0)) {
// start record found so continue
dwFirstValidItem = dwItem;
// step through the remaining entries
while (dwItem < dwNumEntries) {
// get value of this instance if next counter is valid
if ((pNewCounter->CStatus == PDH_CSTATUS_VALID_DATA) ||
(pNewCounter->CStatus == PDH_CSTATUS_NEW_DATA)) {
dwLastValidItem = dwItem;
cStatusReturn = PdhiComputeFormattedValue (
pCounter->CalcFunc,
pCounter->plCounterInfo.dwCounterType,
pCounter->lScale,
dwComputeFormat,
pNewCounter,
pOldCounter,
& pCounter->TimeBase,
0L,
& fmtValue);
if (cStatusReturn == ERROR_SUCCESS) {
dThisValue = fmtValue.doubleValue;
if (bFirstItem) {
dMin = dMax = dThisValue;
bFirstItem = FALSE;
}
else {
if (dThisValue > dMax) dMax = dThisValue;
if (dThisValue < dMin) dMin = dThisValue;
}
dMean += dThisValue;
dwValidItemCount ++;
}
}
pOldCounter = pNewCounter;
pNewCounter++;
dwItem++;
}
// compute average
if (dwValidItemCount > 0) {
dMean /= (double)dwValidItemCount;
if (!(dwFormat & PDH_FMT_NOSCALE)) {
//now scale
dScale = pow (10.0, (double)pCounter->lScale);
dMean *= dScale;
dMin *= dScale;
dMax *= dScale;
}
cStatusReturn = PDH_CSTATUS_VALID_DATA;
} else {
dMean = 0.0;
dMax = 0.0;
dMin = 0.0;
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
}
} else {
// array does not contain a valid counter so exit
dMean = 0.0;
dMax = 0.0;
dMin = 0.0;
cStatusReturn = PDH_CSTATUS_INVALID_DATA;
}
// update user's buffer with new data
data->dwFormat = dwFormat;
data->count = dwValidItemCount;
data->min.CStatus = cStatusReturn;
data->max.CStatus = cStatusReturn;
data->mean.CStatus = cStatusReturn;
switch ((dwFormat & PDHI_FMT_FILTER)) {
case PDH_FMT_LONG:
if (dMin > (DOUBLE) MAXLONG) {
data->min.longValue = MAXLONG;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->min.longValue = (long) dMin;
}
if (dMax > (DOUBLE) MAXLONG) {
data->max.longValue = MAXLONG;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->max.longValue = (long) dMax;
}
if (dMean > (DOUBLE) MAXLONG) {
data->mean.longValue = MAXLONG;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->mean.longValue = (long) dMean;
}
break;
case PDH_FMT_DOUBLE:
data->min.doubleValue = dMin;
data->max.doubleValue = dMax;
data->mean.doubleValue = dMean;
break;
case PDH_FMT_LARGE:
default:
if (dMin > (DOUBLE) MAXLONGLONG) {
data->min.largeValue = MAXLONGLONG;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->min.largeValue = (LONGLONG) dMin;
}
if (dMax > (DOUBLE) MAXLONGLONG) {
data->max.largeValue = MAXLONGLONG;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->max.largeValue = (LONGLONG) dMax;
}
if (dMean > (DOUBLE) MAXLONGLONG) {
data->mean.largeValue = MAXLONGLONG;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
}
else {
data->mean.largeValue = (LONGLONG) dMean;
}
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
return PDH_INVALID_ARGUMENT;
}
return ERROR_SUCCESS;
}
PDH_STATUS
APIENTRY
PdhiComputeNoDataStats (
IN PPDHI_COUNTER pCounter,
IN DWORD dwFormat,
IN DWORD dwFirstEntry,
IN DWORD dwNumEntries,
IN PPDH_RAW_COUNTER lpRawValueArray,
IN PPDH_STATISTICS data
)
{
UNREFERENCED_PARAMETER (pCounter);
UNREFERENCED_PARAMETER (dwFirstEntry);
UNREFERENCED_PARAMETER (dwNumEntries);
UNREFERENCED_PARAMETER (lpRawValueArray);
__try {
data->dwFormat = dwFormat;
data->count = 0;
data->min.CStatus = PDH_CSTATUS_INVALID_DATA;
data->max.CStatus = PDH_CSTATUS_INVALID_DATA;
data->mean.CStatus = PDH_CSTATUS_INVALID_DATA;
switch ((dwFormat & PDHI_FMT_FILTER)) {
case PDH_FMT_LONG:
data->min.doubleValue = 0;
data->max.longValue = 0;
data->mean.longValue = 0;
break;
case PDH_FMT_DOUBLE:
data->min.doubleValue = (double)0;
data->max.doubleValue = (double)0;
data->mean.doubleValue = (double)0.0;
break;
case PDH_FMT_LARGE:
default:
data->min.largeValue = 0;
data->max.largeValue = 0;
data->mean.largeValue = 0;
break;
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
return PDH_INVALID_ARGUMENT;
}
return ERROR_SUCCESS;
}