• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

markrogoyski / math-php / 18643596926

20 Oct 2025 05:59AM UTC coverage: 99.682% (-0.01%) from 99.693%
18643596926

push

github

markrogoyski
Add unit tests.

8154 of 8180 relevant lines covered (99.68%)

230.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.78
/src/Probability/Distribution/Continuous/LogLogistic.php
1
<?php
2

3
namespace MathPHP\Probability\Distribution\Continuous;
4

5
use MathPHP\Functions\Support;
6

7
/**
8
 * Log-logistic distribution
9
 * Also known as the Fisk distribution.
10
 * https://en.wikipedia.org/wiki/Log-logistic_distribution
11
 */
12
class LogLogistic extends Continuous
13
{
14
    /**
15
     * Distribution parameter bounds limits
16
     * α ∈ (0,∞)
17
     * β ∈ (0,∞)
18
     * @var array{"α": string, "β": string}
19
     */
20
    public const PARAMETER_LIMITS = [
21
        'α' => '(0,∞)',
22
        'β' => '(0,∞)',
23
    ];
24

25
    /**
26
     * Distribution support bounds limits
27
     * x ∈ [0,∞)
28
     * @var array{x: string}
29
     */
30
    public const SUPPORT_LIMITS = [
31
        'x' => '[0,∞)',
32
    ];
33

34
     /** @var float Scale Parameter */
35
    protected $α;
36

37
    /** @var float Shape Parameter */
38
    protected $β;
39

40
    /**
41
     * Constructor
42
     *
43
     * @param float $α scale parameter α > 0
44
     * @param float $β shape parameter β > 0
45
     */
46
    public function __construct(float $α, float $β)
47
    {
48
        parent::__construct($α, $β);
88✔
49
    }
88✔
50

51
    /**
52
     * Probability density function
53
     *
54
     *              (β/α)(x/α)ᵝ⁻¹
55
     * f(x; α, β) = -------------
56
     *              (1 + (x/α)ᵝ)²
57
     *
58
     * @param float $x (x > 0)
59
     *
60
     * @return float
61
     */
62

63
    public function pdf(float $x): float
64
    {
65
        Support::checkLimits(self::SUPPORT_LIMITS, ['x' => $x]);
22✔
66

67
        $α = $this->α;
22✔
68
        $β = $this->β;
22✔
69

70
        // Note: Avoid raising 0 to negative exponent (deprecated in PHP 8)
71
        // This represents a singularity at x = 0 when β < 1
72
        $ᵝ⁻¹       = $β - 1;
22✔
73
        $⟮x/α⟯ᵝ⁻¹ = ($x == 0 && $ᵝ⁻¹ < 0)
22✔
74
            ? \INF
×
75
            : \pow($x / $α, $ᵝ⁻¹);
22✔
76

77
        $⟮β/α⟯⟮x/α⟯ᵝ⁻¹  = ($β / $α) * $⟮x/α⟯ᵝ⁻¹;
22✔
78

79
        $⟮1 + ⟮x/α⟯ᵝ⟯² = \pow(1 + ($x / $α) ** $β, 2);
22✔
80

81
        return $⟮β/α⟯⟮x/α⟯ᵝ⁻¹ / $⟮1 + ⟮x/α⟯ᵝ⟯²;
22✔
82
    }
83

84
    /**
85
     * Cumulative distribution function
86
     *
87
     *                   1
88
     * F(x; α, β) = -----------
89
     *              1 + (x/α)⁻ᵝ
90
     *
91
     * @param float $x (x > 0)
92
     *
93
     * @return float
94
     */
95
    public function cdf(float $x): float
96
    {
97
        Support::checkLimits(self::SUPPORT_LIMITS, ['x' => $x]);
44✔
98

99
        $α = $this->α;
44✔
100
        $β = $this->β;
44✔
101

102
        // Note: Avoid raising 0 to negative exponent (deprecated in PHP 8)
103
        // When x = 0, (x/α)⁻ᵝ = 0⁻ᵝ = ∞, so cdf = 1/(1+∞) = 0
104
        $⟮x/α⟯⁻ᵝ = ($x == 0)
44✔
105
            ? \INF
6✔
106
            : \pow($x / $α, -$β);
44✔
107

108
        return 1 / (1 + $⟮x/α⟯⁻ᵝ);
44✔
109
    }
110

111
    /**
112
     * Inverse CDF (Quantile function)
113
     *
114
     *                 /   p   \ 1/β
115
     * F⁻¹(p;α,β) = α |  -----  |
116
     *                 \ 1 - p /
117
     *
118
     * @param float $p
119
     *
120
     * @return float
121
     */
122
    public function inverse(float $p): float
123
    {
124
        Support::checkLimits(['p' => '[0,1]'], ['p' => $p]);
22✔
125

126
        $α = $this->α;
22✔
127
        $β = $this->β;
22✔
128

129
        return $α * ($p / (1 - $p)) ** (1 / $β);
22✔
130
    }
131

132
    /**
133
     * Mean of the distribution
134
     *
135
     *      απ / β
136
     * μ = --------  if β > 1, else undefined
137
     *     sin(π/β)
138
     *
139
     * @return float
140
     */
141
    public function mean(): float
142
    {
143
        $α = $this->α;
8✔
144
        $β = $this->β;
8✔
145
        $π = \M_PI;
8✔
146

147
        if ($β > 1) {
8✔
148
            return (($α * $π) / $β) / \sin($π / $β);
4✔
149
        }
150

151
        return \NAN;
4✔
152
    }
153

154
    /**
155
     * Median of the distribution
156
     *
157
     * median = α
158
     *
159
     * @return float
160
     */
161
    public function median(): float
162
    {
163
        return $this->α;
4✔
164
    }
165

166
    /**
167
     * Mode of the distribution
168
     *
169
     * mode = 0                 β ≤ 1
170
     *
171
     *           / β - 1 \ 1/β
172
     * mode = α |  -----  |     β > 1
173
     *           \ β + 1 /
174
     *
175
     * @return float
176
     */
177
    public function mode(): float
178
    {
179
        $α = $this->α;
6✔
180
        $β = $this->β;
6✔
181

182
        if ($β <= 1) {
6✔
183
            return 0;
3✔
184
        }
185

186
        return $α * \pow(($β - 1) / ($β + 1), 1 / $β);
3✔
187
    }
188

189
    /**
190
     * Variance of the distribution
191
     *
192
     *              /   2β       β²  \
193
     * var[X] = α² |  ------ - -----  |    β > 2
194
     *              \ sin 2β   sin²β  /
195
     *
196
     * @return float
197
     */
198
    public function variance(): float
199
    {
200
        $α = $this->α;
4✔
201
        $β = $this->β;
4✔
202

203
        if ($β <= 2) {
4✔
204
            return \NAN;
2✔
205
        }
206

207
        $α²    = $α ** 2;
2✔
208
        $β²    = $β ** 2;
2✔
209
        $2β   = 2 * $β;
2✔
210
        $sin2β = \sin($2β);
2✔
211
        $sin²β = \sin($β) ** 2;
2✔
212

213
        return $α² * (($2β / $sin2β) - ($β² / $sin²β));
2✔
214
    }
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc