Failed Conditions
Pull Request — dev (#50)
by Jordan
06:20
created

StatsProvider   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 252
Duplicated Lines 0 %

Test Coverage

Coverage 17.34%

Importance

Changes 0
Metric Value
eloc 106
dl 0
loc 252
ccs 17
cts 98
cp 0.1734
rs 10
c 0
b 0
f 0
wmc 17

7 Methods

Rating   Name   Duplication   Size   Complexity  
A gaussErrorFunction() 0 35 1
A complementNormalCDF() 0 6 1
A inverseGaussErrorFunction() 0 38 3
A binomialCoefficient() 0 23 5
A inverseErrorCoefficients() 0 34 5
A normalCDF() 0 35 1
A inverseNormalCDF() 0 11 1
1
<?php
2
3
namespace Samsara\Fermat\Provider;
4
5
use Ds\Vector;
6
use Samsara\Exceptions\UsageError\IntegrityConstraint;
7
use Samsara\Exceptions\SystemError\LogicalError\IncompatibleObjectState;
8
use Samsara\Exceptions\UsageError\OptionalExit;
9
use Samsara\Fermat\Numbers;
10
use Samsara\Fermat\Types\Base\Interfaces\Numbers\NumberInterface;
11
use Samsara\Fermat\Types\Base\Interfaces\Numbers\DecimalInterface;
12
use Samsara\Fermat\Types\Base\Interfaces\Numbers\FractionInterface;
13
use Samsara\Fermat\Values\ImmutableDecimal;
14
use Samsara\Fermat\Values\ImmutableFraction;
15
16
class StatsProvider
17
{
18
19
    /**
20
     * @var Vector
21
     */
22
    protected static $inverseErrorCoefs;
23
24
    /**
25
     * @param $x
26
     *
27
     * @return NumberInterface
28
     * @throws IntegrityConstraint
29
     * @throws OptionalExit|\ReflectionException
30
     */
31
    public static function normalCDF($x): ImmutableDecimal
32
    {
33
        $x = Numbers::makeOrDont(Numbers::IMMUTABLE, $x);
34
35
        $precision = $x->getPrecision();
36
        $internalPrecision = $precision+2;
37
38
        $pi = Numbers::makePi($internalPrecision);
39
        $e = Numbers::makeE($internalPrecision);
40
        $one = Numbers::makeOne($internalPrecision);
41
42
        $eExponent = Numbers::make(Numbers::IMMUTABLE, $x->getValue());
0 ignored issues
show
Bug introduced by
The method getValue() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Samsara\Fermat\Types\Bas...Numbers\NumberInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

42
        $eExponent = Numbers::make(Numbers::IMMUTABLE, $x->/** @scrutinizer ignore-call */ getValue());
Loading history...
43
        $eExponent = $eExponent->pow(2)->divide(2)->multiply(-1);
44
45
        $answer = Numbers::make(Numbers::IMMUTABLE, 0.5);
46
        $answer = $answer->add(
47
            $one->divide($pi->multiply(2)->sqrt())
48
                ->multiply($e->pow($eExponent))
49
                ->multiply(SeriesProvider::maclaurinSeries(
50
                    $x,
0 ignored issues
show
Bug introduced by
It seems like $x can also be of type Samsara\Fermat\Types\Bas...mbers\NumberInterface[] and Samsara\Fermat\Values\ImmutableDecimal[] and Samsara\Fermat\Values\MutableDecimal[]; however, parameter $input of Samsara\Fermat\Provider\...ider::maclaurinSeries() does only seem to accept Samsara\Fermat\Types\Bas...s\SimpleNumberInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

50
                    /** @scrutinizer ignore-type */ $x,
Loading history...
51
                    function ($n) {
0 ignored issues
show
Unused Code introduced by
The parameter $n is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

51
                    function (/** @scrutinizer ignore-unused */ $n) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
52
                        return Numbers::makeOne();
53
                    },
54
                    function ($n) {
55
                        return SequenceProvider::nthOddNumber($n);
56
                    },
57
                    function ($n) {
58
                        return SequenceProvider::nthOddNumber($n)->doubleFactorial();
0 ignored issues
show
Bug introduced by
The method doubleFactorial() does not exist on Samsara\Fermat\Types\NumberCollection. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

58
                        return SequenceProvider::nthOddNumber($n)->/** @scrutinizer ignore-call */ doubleFactorial();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method doubleFactorial() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of Samsara\Fermat\Types\Bas...Numbers\NumberInterface such as Samsara\Fermat\Types\Bas...umbers\DecimalInterface or Samsara\Fermat\Types\Decimal. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

58
                        return SequenceProvider::nthOddNumber($n)->/** @scrutinizer ignore-call */ doubleFactorial();
Loading history...
59
                    },
60
                    0,
61
                    $internalPrecision
62
                ))
63
        );
64
65
        return $answer->truncateToPrecision($precision);
0 ignored issues
show
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Types\Bas...mbers\FractionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of Samsara\Fermat\Types\Bas...Numbers\NumberInterface such as Samsara\Fermat\Types\Bas...umbers\DecimalInterface or Samsara\Fermat\Types\Decimal. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);
Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Types\Bas...\ComplexNumberInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Values\ImmutableFraction. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Types\Bas...tes\CoordinateInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Values\Ge...ems\CartesianCoordinate. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug Best Practice introduced by
The expression return $answer->truncateToPrecision($precision) could return the type Samsara\Fermat\Types\Bas...umbers\DecimalInterface which includes types incompatible with the type-hinted return Samsara\Fermat\Values\ImmutableDecimal. Consider adding an additional type-check to rule them out.
Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Values\ImmutableComplexNumber. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Values\MutableFraction. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method truncateToPrecision() does not exist on Samsara\Fermat\Values\MutableComplexNumber. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return $answer->/** @scrutinizer ignore-call */ truncateToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
66
67
    }
68
69
    /**
70
     * @param $x
71
     *
72
     * @return DecimalInterface|NumberInterface
73
     * @throws IntegrityConstraint
74
     * @throws OptionalExit
75
     */
76
    public static function complementNormalCDF($x): ImmutableDecimal
77
    {
78
        $p = self::normalCDF($x);
79 1
        $one = Numbers::makeOne();
80
81
        return $one->subtract($p);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $one->subtract($p) could return the type Samsara\Fermat\Values\ImmutableComplexNumber which is incompatible with the type-hinted return Samsara\Fermat\Values\ImmutableDecimal. Consider adding an additional type-check to rule them out.
Loading history...
82 1
    }
83 1
84 1
    /**
85
     * @param $x
86 1
     *
87
     * @return DecimalInterface|FractionInterface|NumberInterface|ImmutableDecimal
88 1
     * @throws IntegrityConstraint
89 1
     * @throws OptionalExit
90 1
     */
91
    public static function gaussErrorFunction($x): ImmutableDecimal
92 1
    {
93
94 1
        $x = Numbers::makeOrDont(Numbers::IMMUTABLE, $x);
95 1
96
        $precision = $x->getPrecision();
97 1
        $internalPrecision = $precision + 2;
98 1
99
        $answer = Numbers::makeOne($internalPrecision);
100 1
        $pi = Numbers::makePi($internalPrecision);
101
102 1
        $answer = $answer->multiply(2)->divide($pi->sqrt());
103 1
104
        $answer = $answer->multiply(
105
            SeriesProvider::maclaurinSeries(
106
                $x,
0 ignored issues
show
Bug introduced by
It seems like $x can also be of type Samsara\Fermat\Types\Bas...mbers\NumberInterface[] and Samsara\Fermat\Values\ImmutableDecimal[] and Samsara\Fermat\Values\MutableDecimal[]; however, parameter $input of Samsara\Fermat\Provider\...ider::maclaurinSeries() does only seem to accept Samsara\Fermat\Types\Bas...s\SimpleNumberInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
                /** @scrutinizer ignore-type */ $x,
Loading history...
107 1
                function ($n) {
108
                    $negOne = Numbers::make(Numbers::IMMUTABLE, -1);
109
110
                    return $negOne->pow($n);
111
                },
112
                function ($n) {
113
                    return SequenceProvider::nthOddNumber($n);
114
                },
115
                function ($n) {
116
                    $n = Numbers::makeOrDont(Numbers::IMMUTABLE, $n);
117
118
                    return $n->factorial()->multiply(SequenceProvider::nthOddNumber($n->asInt()));
0 ignored issues
show
Bug introduced by
The method asInt() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of Samsara\Fermat\Types\Bas...Numbers\NumberInterface such as Samsara\Fermat\Types\Bas...umbers\DecimalInterface or Samsara\Fermat\Types\Decimal. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
                    return $n->factorial()->multiply(SequenceProvider::nthOddNumber($n->/** @scrutinizer ignore-call */ asInt()));
Loading history...
Bug introduced by
The method factorial() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of Samsara\Fermat\Types\Bas...Numbers\NumberInterface such as Samsara\Fermat\Types\Bas...umbers\DecimalInterface or Samsara\Fermat\Types\Decimal. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
                    return $n->/** @scrutinizer ignore-call */ factorial()->multiply(SequenceProvider::nthOddNumber($n->asInt()));
Loading history...
119
                },
120
                0,
121
                $internalPrecision
122
            )
123
        );
124
125
        return $answer->truncateToPrecision($precision);
126
127
    }
128
129
    /**
130
     * @param     $p
131
     * @param int $precision
132
     *
133
     * @return DecimalInterface|NumberInterface|ImmutableDecimal
134
     * @throws IntegrityConstraint
135
     * @throws OptionalExit
136
     */
137
    public static function inverseNormalCDF($p, int $precision = 10): ImmutableDecimal
138
    {
139
        $p = Numbers::makeOrDont(Numbers::IMMUTABLE, $p);
140
141
        $precision = $precision ?? $p->getPrecision();
142
        $internalPrecision = $precision + 2;
143
144
        $two = Numbers::make(Numbers::IMMUTABLE, 2, $internalPrecision);
145
        $invErfArg = $two->multiply($p)->subtract(1);
146
147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->roundToPrecision($precision);
0 ignored issues
show
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Values\ImmutableComplexNumber. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Types\Bas...tes\CoordinateInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Values\ImmutableFraction. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Values\Ge...ems\CartesianCoordinate. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Values\MutableComplexNumber. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Types\Bas...mbers\FractionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Values\MutableFraction. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method roundToPrecision() does not exist on Samsara\Fermat\Types\Bas...\ComplexNumberInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

147
        return StatsProvider::inverseGaussErrorFunction($invErfArg, $internalPrecision)->multiply($two->sqrt($internalPrecision))->/** @scrutinizer ignore-call */ roundToPrecision($precision);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
148
    }
149
150
    /**
151
     * @param $n
152
     * @param $k
153
     *
154
     * @return DecimalInterface|NumberInterface|ImmutableDecimal
155
     * @throws IntegrityConstraint
156
     * @throws IncompatibleObjectState
157
     */
158
    public static function binomialCoefficient($n, $k): ImmutableDecimal
159
    {
160
161
        $n = Numbers::makeOrDont(Numbers::IMMUTABLE, $n);
162
        $k = Numbers::makeOrDont(Numbers::IMMUTABLE, $k);
163
164
        if ($k->isLessThan(0) || $n->isLessThan($k)) {
0 ignored issues
show
Bug introduced by
The method isLessThan() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of Samsara\Fermat\Types\Bas...Numbers\NumberInterface such as Samsara\Fermat\Types\Bas...s\SimpleNumberInterface or Samsara\Fermat\Types\Fraction or Samsara\Fermat\Types\Decimal. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

164
        if ($k->/** @scrutinizer ignore-call */ isLessThan(0) || $n->isLessThan($k)) {
Loading history...
165
            throw new IntegrityConstraint(
166
                '$k must be larger or equal to 0 and less than or equal to $n',
167
                'Provide valid $n and $k values such that 0 <= $k <= $n',
168
                'For $n choose $k, the values of $n and $k must satisfy the inequality 0 <= $k <= $n'
169
            );
170
        }
171
172
        if (!$n->isInt() || !$k->isInt()) {
0 ignored issues
show
Bug introduced by
The method isInt() does not exist on Samsara\Fermat\Types\Bas...Numbers\NumberInterface. It seems like you code against a sub-type of Samsara\Fermat\Types\Bas...Numbers\NumberInterface such as Samsara\Fermat\Types\Bas...umbers\DecimalInterface or Samsara\Fermat\Types\Fraction or Samsara\Fermat\Types\Fraction or Samsara\Fermat\Types\Decimal. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
        if (!$n->/** @scrutinizer ignore-call */ isInt() || !$k->isInt()) {
Loading history...
173
            throw new IntegrityConstraint(
174
                '$k and $n must be whole numbers',
175
                'Provide whole numbers for $n and $k',
176
                'For $n choose $k, the values $n and $k must be whole numbers'
177
            );
178
        }
179
180
        return $n->factorial()->divide($k->factorial()->multiply($n->subtract($k)->factorial()));
0 ignored issues
show
Bug introduced by
The method factorial() does not exist on Samsara\Fermat\Values\ImmutableComplexNumber. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
        return $n->factorial()->divide($k->factorial()->multiply($n->subtract($k)->/** @scrutinizer ignore-call */ factorial()));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method factorial() does not exist on Samsara\Fermat\Types\Bas...mbers\FractionInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
        return $n->factorial()->divide($k->factorial()->multiply($n->subtract($k)->/** @scrutinizer ignore-call */ factorial()));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
181
182
    }
183
184
    public static function inverseErrorCoefficients(int $termIndex): ImmutableFraction
185
    {
186
187
        $terms =& static::$inverseErrorCoefs;
188
189
        if (is_null(static::$inverseErrorCoefs)) {
190
            $terms = new Vector();
191
            $terms->push(new ImmutableFraction(Numbers::makeOne(), Numbers::makeOne()));
192
            $terms->push(new ImmutableFraction(Numbers::makeOne(), Numbers::makeOne()));
193
        }
194
195
        if ($terms->offsetExists($termIndex)) {
196
            return $terms->get($termIndex);
197
        }
198
199
        $nextTerm = $terms->count();
200
201
        for ($k = $nextTerm;$k <= $termIndex;$k++) {
202
            $termValue = new ImmutableFraction(new ImmutableDecimal('0'), new ImmutableDecimal('1'));
203
            for ($m = 0;$m <= ($k - 1);$m++) {
204
                $part1 = $terms->get($m);
205
                $part2 = $terms->get($k - 1 - $m);
206
                $part3 = $part1->multiply($part2);
207
                $part4 = ($m + 1)*($m*2 + 1);
208
                $part5 = $part3->divide($part4);
209
                $termValue = $termValue->add($part5);
210
            }
211
212
            $termValue = $termValue->simplify();
213
214
            $terms->push($termValue);
215
        }
216
217
        return $terms->get($termIndex);
218
219
    }
220
221
    /**
222
     * @param $z
223
     * @param int $precision
224
     *
225
     * @return ImmutableDecimal
226
     * @throws IntegrityConstraint
227
     * @throws OptionalExit
228
     * @throws \ReflectionException
229
     */
230
    public static function inverseGaussErrorFunction($z, int $precision = 10): ImmutableDecimal
231
    {
232
233
        $z = Numbers::makeOrDont(Numbers::IMMUTABLE, $z);
234
235
        $precision = $precision ?? $z->getPrecision();
236
        $internalPrecision = $precision + 1;
237
238
        $pi = Numbers::makePi($internalPrecision);
239
240
        $answer = SeriesProvider::maclaurinSeries(
241
            $z,
0 ignored issues
show
Bug introduced by
It seems like $z can also be of type Samsara\Fermat\Types\Bas...mbers\NumberInterface[] and Samsara\Fermat\Values\ImmutableDecimal[] and Samsara\Fermat\Values\MutableDecimal[]; however, parameter $input of Samsara\Fermat\Provider\...ider::maclaurinSeries() does only seem to accept Samsara\Fermat\Types\Bas...s\SimpleNumberInterface, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

241
            /** @scrutinizer ignore-type */ $z,
Loading history...
242
            function ($n) use ($pi) {
243
                if ($n > 0) {
244
                    return $pi->pow($n)->multiply(StatsProvider::inverseErrorCoefficients($n));
245
                }
246
247
                return Numbers::makeOne();
248
            },
249
            function ($n) {
250
                return SequenceProvider::nthOddNumber($n);
251
            },
252
            function ($n) {
253
                if ($n > 0) {
254
                    $extra = Numbers::make(Numbers::IMMUTABLE, 2)->pow(SequenceProvider::nthEvenNumber($n));
255
                } else {
256
                    $extra = Numbers::makeOne();
257
                }
258
259
                return SequenceProvider::nthOddNumber($n)->multiply($extra);
260
            },
261
            0,
262
            $internalPrecision
263
        );
264
265
        $answer = $answer->multiply($pi->sqrt($internalPrecision)->divide(2, $internalPrecision));
266
267
        return $answer->roundToPrecision($precision);
268
269
    }
270
271
}