190c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein#ifndef Stats_DEFINED
290c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein#define Stats_DEFINED
390c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein
45d9d10e8217d2138b5514a4d4216f95373240942mtklein#include "SkString.h"
540b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein#include "SkTSort.h"
640b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein
76238688af0d758660d344ec047243d4efefd6f4dmtklein#ifdef SK_BUILD_FOR_WIN
86238688af0d758660d344ec047243d4efefd6f4dmtklein    static const char* kBars[] = { ".", "o", "O" };
96238688af0d758660d344ec047243d4efefd6f4dmtklein#else
106238688af0d758660d344ec047243d4efefd6f4dmtklein    static const char* kBars[] = { "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" };
116238688af0d758660d344ec047243d4efefd6f4dmtklein#endif
125d9d10e8217d2138b5514a4d4216f95373240942mtklein
1390c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtkleinstruct Stats {
1490c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein    Stats(const double samples[], int n) {
1590c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        min = samples[0];
1690c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        max = samples[0];
1790c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        for (int i = 0; i < n; i++) {
1890c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein            if (samples[i] < min) { min = samples[i]; }
1990c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein            if (samples[i] > max) { max = samples[i]; }
2090c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        }
2190c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein
2290c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        double sum = 0.0;
2390c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        for (int i = 0 ; i < n; i++) {
2490c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein            sum += samples[i];
2590c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        }
2690c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        mean = sum / n;
2790c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein
2890c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        double err = 0.0;
2990c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        for (int i = 0 ; i < n; i++) {
3090c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein            err += (samples[i] - mean) * (samples[i] - mean);
3190c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        }
3290c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein        var = err / (n-1);
3340b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein
3440b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkAutoTMalloc<double> sorted(n);
3540b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        memcpy(sorted.get(), samples, n * sizeof(double));
3640b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        SkTQSort(sorted.get(), sorted.get() + n - 1);
3740b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein        median = sorted[n/2];
385d9d10e8217d2138b5514a4d4216f95373240942mtklein
39a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein        // Normalize samples to [min, max] in as many quanta as we have distinct bars to print.
405d9d10e8217d2138b5514a4d4216f95373240942mtklein        for (int i = 0; i < n; i++) {
41a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            if (min == max) {
42a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                // All samples are the same value.  Don't divide by zero.
43a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                plot.append(kBars[0]);
44a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein                continue;
45a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein            }
46a189ccdb4d5efdbbfa34a26c08656634b615f930mtklein
475d9d10e8217d2138b5514a4d4216f95373240942mtklein            double s = samples[i];
485d9d10e8217d2138b5514a4d4216f95373240942mtklein            s -= min;
495d9d10e8217d2138b5514a4d4216f95373240942mtklein            s /= (max - min);
505d9d10e8217d2138b5514a4d4216f95373240942mtklein            s *= (SK_ARRAY_COUNT(kBars) - 1);
51912947737a973421f4c58682b6171cb5ee00ad3aMike Klein            const size_t bar = (size_t)(s + 0.5);
525d9d10e8217d2138b5514a4d4216f95373240942mtklein            SK_ALWAYSBREAK(bar < SK_ARRAY_COUNT(kBars));
535d9d10e8217d2138b5514a4d4216f95373240942mtklein            plot.append(kBars[bar]);
545d9d10e8217d2138b5514a4d4216f95373240942mtklein        }
5590c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein    }
5690c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein
5790c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein    double min;
5890c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein    double max;
595d9d10e8217d2138b5514a4d4216f95373240942mtklein    double mean;    // Estimate of population mean.
605d9d10e8217d2138b5514a4d4216f95373240942mtklein    double var;     // Estimate of population variance.
6140b32be3718f0f2e01c4a21bb0004b7f93670c42mtklein    double median;
625d9d10e8217d2138b5514a4d4216f95373240942mtklein    SkString plot;  // A single-line bar chart (_not_ histogram) of the samples.
6390c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein};
6490c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein
6590c471e73fb0bd09aef8ad1e3f0842e5d46fb342mtklein#endif//Stats_DEFINED
66