Passed
Push — master ( 8b49d6...8ffc72 )
by Alec
16:03
created

MeasurementsResults   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 34
dl 0
loc 73
ccs 0
cts 34
cp 0
rs 10
c 0
b 0
f 0
wmc 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A convertDataType() 0 11 3
A createResult() 0 15 1
A removeMax() 0 4 1
A refine() 0 17 4
A rejectionCoefficient() 0 3 1
1
<?php declare(strict_types=1);
2
3
namespace AlecRabbit\Tools\Internal;
4
5
use MathPHP\Exception\BadDataException;
6
use MathPHP\Exception\OutOfBoundsException;
7
use MathPHP\Statistics\Average;
8
use MathPHP\Statistics\RandomVariable;
9
10
class MeasurementsResults
11
{
12
    protected const REJECTION_THRESHOLD = 100;
13
14
    /**
15
     * @param array $measurements
16
     * @param BenchmarkResult|null $previous
17
     * @return BenchmarkResult
18
     * @throws BadDataException
19
     * @throws OutOfBoundsException
20
     */
21
    public static function createResult(array $measurements, ?BenchmarkResult $previous = null): BenchmarkResult
22
    {
23
        $measurements = self::convertDataType($measurements);
24
        $numberOfRejections = self::refine($measurements, $previous);
25
        $numberOfMeasurements = count($measurements);
26
        $mean = Average::mean($measurements);
27
        $standardErrorOfTheMean = RandomVariable::standardErrorOfTheMean($measurements);
28
        $tValue = TDistribution::tValue($numberOfMeasurements);
29
30
        return
31
            new BenchmarkResult(
32
                $mean,
33
                $standardErrorOfTheMean * $tValue,
34
                $numberOfMeasurements,
35
                $numberOfRejections
36
            );
37
    }
38
39
    protected static function convertDataType(array $measurements): array
40
    {
41
        if ($measurements[0] instanceof BenchmarkResult) {
42
            $m = [];
43
            /** @var BenchmarkResult $r */
44
            foreach ($measurements as $r) {
45
                $m[] = $r->getMean();
46
            }
47
            $measurements = $m;
48
        }
49
        return $measurements;
50
    }
51
52
    protected static function refine(array &$measurements, ?BenchmarkResult $previous = null): int
53
    {
54
        self::removeMax($measurements);
55
        $rejections = 0;
56
        if ($previous instanceof BenchmarkResult) {
57
            $meanThreshold = $previous->getMean() * self::rejectionCoefficient();
58
        } else {
59
            $meanThreshold = Average::mean($measurements) * self::rejectionCoefficient();
60
        }
61
62
        foreach ($measurements as $key => $value) {
63
            if ($value > $meanThreshold) {
64
                unset($measurements[$key]);
65
                $rejections++;
66
            }
67
        }
68
        return $rejections;
69
    }
70
71
    protected static function removeMax(array &$measurements): void
72
    {
73
        $max = max($measurements);
74
        unset($measurements[array_search($max, $measurements, true)]);
75
    }
76
77
    /**
78
     * @return float|int
79
     */
80
    protected static function rejectionCoefficient()
81
    {
82
        return 1 + self::REJECTION_THRESHOLD / 100;
83
    }
84
}
85