using System;
class Entropy {
public static void Main(string[] args)
{
const int arraySize = 1024*1024*16;
double[] p = new double[arraySize];
Random rng = new Random();
for (int i = 0; i < arraySize; i++)
{
p[i] = 1.0 - rng.NextDouble();
}
ulong frequency = Yeppp.Library.GetTimerFrequency();
ulong startTimeNaive = Yeppp.Library.GetTimerTicks();
double entropyNaive = computeEntropyNaive(p);
ulong endTimeNaive = Yeppp.Library.GetTimerTicks();
ulong startTimeYepppSafe = Yeppp.Library.GetTimerTicks();
double entropyYepppSafe = computeEntropyYepppSafe(p);
ulong endTimeYepppSafe = Yeppp.Library.GetTimerTicks();
ulong startTimeYepppUnsafe = Yeppp.Library.GetTimerTicks();
double entropyYepppUnsafe = computeEntropyYepppUnsafe(p);
ulong endTimeYepppUnsafe = Yeppp.Library.GetTimerTicks();
Console.WriteLine("Naive implementation:");
Console.WriteLine("\tEntropy = {0:F}", entropyNaive);
Console.WriteLine("\tTime = {0:F} secs", ((double)(endTimeNaive - startTimeNaive)) / ((double)(frequency)));
Console.WriteLine("Yeppp! implementation (safe):");
Console.WriteLine("\tEntropy = {0:F}", entropyYepppSafe);
Console.WriteLine("\tTime = {0:F} secs", ((double)(endTimeYepppSafe - startTimeYepppSafe)) / ((double)(frequency)));
Console.WriteLine("Yeppp! implementation (unsafe):");
Console.WriteLine("\tEntropy = {0:F}", entropyYepppUnsafe);
Console.WriteLine("\tTime = {0:F} secs", ((double)(endTimeYepppUnsafe - startTimeYepppUnsafe)) / ((double)(frequency)));
}
private static double computeEntropyNaive(double[] probabilities)
{
double entropy = 0.0;
for (int i = 0; i < probabilities.Length; i++)
{
double p = probabilities[i];
entropy -= p * Math.Log(p);
}
return entropy;
}
private static double computeEntropyYepppSafe(double[] p)
{
double entropy = 0.0;
const int blockSize = 1024;
double[] logP = new double[blockSize];
for (int index = 0; index < p.Length; index += blockSize)
{
int blockLength = Math.Min(blockSize, p.Length - index);
Yeppp.Math.Log_V64f_V64f(p, index, logP, 0, blockLength);
double dotProduct = Yeppp.Core.DotProduct_V64fV64f_S64f(p, index, logP, 0, blockLength);
entropy -= dotProduct;
}
return entropy;
}
private static unsafe double computeEntropyYepppUnsafe(double[] probabilities)
{
double entropy = 0.0;
const int blockSize = 1024;
double* logP = stackalloc double[blockSize];
fixed (double* p = &probabilities[0])
{
for (int index = 0; index < probabilities.Length; index += blockSize)
{
int blockLength = Math.Min(blockSize, probabilities.Length - index);
Yeppp.Math.Log_V64f_V64f(p + index, logP, blockLength);
double dotProduct = Yeppp.Core.DotProduct_V64fV64f_S64f(p + index, logP, blockLength);
entropy -= dotProduct;
}
}
return entropy;
}
}