Failed Conditions
Push — master ( 67fec4...924347 )
by Adrien
07:48
created

ChiSquared::inverse()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 14
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 24
ccs 14
cts 14
cp 1
crap 5
rs 9.4888
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
4
5
use PhpOffice\PhpSpreadsheet\Calculation\Exception;
6
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
7
8
class ChiSquared
9
{
10
    use BaseValidations;
11
12
    private const MAX_ITERATIONS = 256;
13
14
    /**
15
     * CHIDIST.
16
     *
17
     * Returns the one-tailed probability of the chi-squared distribution.
18
     *
19
     * @param mixed (float) $value Value for the function
20
     * @param mixed (int) $degrees degrees of freedom
21
     *
22
     * @return float|string
23
     */
24 16
    public static function distribution($value, $degrees)
25
    {
26 16
        $value = Functions::flattenSingleValue($value);
27 16
        $degrees = Functions::flattenSingleValue($degrees);
28
29
        try {
30 16
            $value = self::validateFloat($value);
31 15
            $degrees = self::validateInt($degrees);
32 2
        } catch (Exception $e) {
33 2
            return $e->getMessage();
34
        }
35
36 14
        if ($degrees < 1) {
37 1
            return Functions::NAN();
38
        }
39 13
        if ($value < 0) {
40 1
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
41
                return 1;
42
            }
43
44 1
            return Functions::NAN();
45
        }
46
47 12
        return 1 - (Gamma::incompleteGamma($degrees / 2, $value / 2) / Gamma::gammaValue($degrees / 2));
48
    }
49
50
    /**
51
     * CHIINV.
52
     *
53
     * Returns the one-tailed probability of the chi-squared distribution.
54
     *
55
     * @param mixed (float) $probability Probability for the function
56
     * @param mixed (int) $degrees degrees of freedom
57
     *
58
     * @return float|string
59
     */
60 13
    public static function inverse($probability, $degrees)
61
    {
62 13
        $probability = Functions::flattenSingleValue($probability);
63 13
        $degrees = Functions::flattenSingleValue($degrees);
64
65
        try {
66 13
            $probability = self::validateFloat($probability);
67 12
            $degrees = self::validateInt($degrees);
68 2
        } catch (Exception $e) {
69 2
            return $e->getMessage();
70
        }
71
72 11
        if ($probability < 0.0 || $probability > 1.0 || $degrees < 1) {
73 3
            return Functions::NAN();
74
        }
75
76
        $callback = function ($value) use ($degrees) {
77 8
            return 1 - (Gamma::incompleteGamma($degrees / 2, $value / 2)
78 8
                    / Gamma::gammaValue($degrees / 2));
79 8
        };
80
81 8
        $newtonRaphson = new NewtonRaphson($callback);
82
83 8
        return $newtonRaphson->execute($probability);
84
    }
85
86 7
    public static function test($actual, $expected)
87
    {
88 7
        $rows = count($actual);
89 7
        $actual = Functions::flattenArray($actual);
90 7
        $expected = Functions::flattenArray($expected);
91 7
        $columns = count($actual) / $rows;
92
93 7
        $countActuals = count($actual);
94 7
        $countExpected = count($expected);
95 7
        if ($countActuals !== $countExpected || $countActuals === 1) {
96 1
            return Functions::NAN();
97
        }
98
99 6
        $result = 0.0;
100 6
        for ($i = 0; $i < $countActuals; ++$i) {
101 6
            if ($expected[$i] == 0.0) {
102 1
                return Functions::DIV0();
103 6
            } elseif ($expected[$i] < 0.0) {
104 1
                return Functions::NAN();
105
            }
106 6
            $result += (($actual[$i] - $expected[$i]) ** 2) / $expected[$i];
107
        }
108
109 4
        $degrees = self::degrees($rows, $columns);
110
111 4
        $result = self::distribution($result, $degrees);
112
113 4
        return $result;
114
    }
115
116 4
    protected static function degrees(int $rows, int $columns): int
117
    {
118 4
        if ($rows === 1) {
119 1
            return $columns - 1;
120 3
        } elseif ($columns === 1) {
121 1
            return $rows - 1;
122
        }
123
124 2
        return ($columns - 1) * ($rows - 1);
125
    }
126
}
127