package org.opensolaris.os.dtrace;
import java.io.*;
import java.beans.*;
import java.math.BigInteger;
public final class StddevValue extends AbstractAggregationValue {
static final long serialVersionUID = 6409878160513885375L;
private final long total;
private final long count;
private final BigInteger totalSquares;
static {
try {
BeanInfo info = Introspector.getBeanInfo(StddevValue.class);
PersistenceDelegate persistenceDelegate =
new DefaultPersistenceDelegate(
new String[] {"value", "total", "count", "totalSquares"})
{
@Override
protected Expression
instantiate(Object oldInstance, Encoder out)
{
StddevValue stddev = (StddevValue)oldInstance;
return new Expression(oldInstance, oldInstance.getClass(),
"new", new Object[] {
stddev.getValue().longValue(),
stddev.getTotal(), stddev.getCount(),
stddev.getTotalSquares().toString() });
}
};
BeanDescriptor d = info.getBeanDescriptor();
d.setValue("persistenceDelegate", persistenceDelegate);
} catch (IntrospectionException e) {
System.out.println(e);
}
}
private static long
squareRoot128(BigInteger n)
{
long result = 0;
BigInteger diff = BigInteger.valueOf(0);
BigInteger nextTry = BigInteger.valueOf(0);
int bitPairs = (n.bitLength() / 2);
int bitPos = (bitPairs * 2) + 1;
int nextTwoBits;
for (int i = 0; i <= bitPairs; i++) {
nextTwoBits = n.testBit(bitPos)
? (n.testBit(bitPos - 1) ? 0x3 : 0x2)
: (n.testBit(bitPos - 1) ? 0x1 : 0x0);
diff = diff.shiftLeft(2);
diff = diff.add(BigInteger.valueOf(nextTwoBits));
nextTry = BigInteger.valueOf(result);
nextTry = nextTry.shiftLeft(2);
nextTry = nextTry.setBit(0);
result <<= 1;
if (nextTry.compareTo(diff) <= 0) {
diff = diff.subtract(nextTry);
result++;
}
bitPos -= 2;
}
return (result);
}
private static long
standardDeviation(long stddevCount, long stddevTotal,
BigInteger stddevTotalSquares)
{
BigInteger averageOfSquares = stddevTotalSquares.divide(
BigInteger.valueOf(stddevCount));
long avg = (stddevTotal / stddevCount);
if (avg < 0) {
avg = -avg;
}
BigInteger squareOfAverage = BigInteger.valueOf(avg);
squareOfAverage = squareOfAverage.pow(2);
BigInteger stddev = averageOfSquares.subtract(squareOfAverage);
return squareRoot128(stddev);
}
private
StddevValue(long stddevCount, long stddevTotal,
BigInteger stddevTotalSquares)
{
super(stddevCount == 0 ? 0 : standardDeviation(stddevCount,
stddevTotal, stddevTotalSquares));
total = stddevTotal;
count = stddevCount;
totalSquares = stddevTotalSquares;
if (totalSquares == null) {
throw new NullPointerException("totalSquares is null");
}
if (count < 0) {
throw new IllegalArgumentException("count is negative");
}
}
public
StddevValue(long v, long stddevTotal, long stddevCount,
String stddevTotalSquaresString)
{
super(v);
total = stddevTotal;
count = stddevCount;
totalSquares = new BigInteger(stddevTotalSquaresString);
validate();
}
private final void
validate()
{
if (count < 0) {
throw new IllegalArgumentException("count is negative");
}
long stddev = super.getValue().longValue();
if (count == 0) {
if (stddev != 0) {
throw new IllegalArgumentException(
"count of values is zero, stddev is non-zero (" +
stddev + ")");
}
} else {
if (stddev != standardDeviation(count, total, totalSquares)) {
throw new IllegalArgumentException(
getValue().toString() + " is not the expected " +
"standard deviation of total " + total + ", count " +
count + ", and total squares " + totalSquares);
}
}
}
public Long
getValue()
{
return (Long)super.getValue();
}
public long
getTotal()
{
return total;
}
public long
getCount()
{
return count;
}
public BigInteger
getTotalSquares()
{
return totalSquares;
}
private void
readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException
{
s.defaultReadObject();
try {
validate();
} catch (Exception e) {
InvalidObjectException x = new InvalidObjectException(
e.getMessage());
x.initCause(e);
throw x;
}
}
}