Passed
Push — dev ( 535e94...fa082c )
by Jordan
33s queued 10s
created

PolynomialFunction::__construct()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 42
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 22
nc 4
nop 1
dl 0
loc 42
ccs 22
cts 22
cp 1
crap 6
rs 8.9457
c 0
b 0
f 0
1
<?php
2
3
namespace Samsara\Fermat\Values\Algebra;
4
5
use Samsara\Exceptions\UsageError\IntegrityConstraint;
6
use Samsara\Fermat\Numbers;
7
use Samsara\Fermat\Types\Base\DecimalInterface;
8
use Samsara\Fermat\Types\Base\ExpressionInterface;
9
use Samsara\Fermat\Types\Base\FunctionInterface;
10
use Samsara\Fermat\Types\Base\NumberInterface;
11
use Samsara\Fermat\Types\Expression;
12
use Samsara\Fermat\Values\ImmutableNumber;
13
14
class PolynomialFunction extends Expression implements ExpressionInterface, FunctionInterface
15
{
16
    /** @var array  */
17
    protected $coefficients = [];
18
19
    /**
20
     * PolynomialFunction constructor.
21
     *
22
     * @param array $coefficients
23
     *
24
     * @throws IntegrityConstraint
25
     */
26 4
    public function __construct(array $coefficients)
27
    {
28 4
        parent::__construct(Expression::POLYNOMIAL);
29
30 4
        $sanitizedCoefficients = [];
31
32 4
        foreach ($coefficients as $exponent => $coefficient) {
33 4
            if (!is_int($exponent)) {
34 1
                throw new IntegrityConstraint(
35 1
                    'Keys in the $coefficients array must be integers',
36 1
                    'Only use integer keys for the $coefficients array',
37 1
                    'The key '.$exponent.' was found in the $coefficients array; an integer was expected'
38
                );
39
            }
40
41
            /** @var ImmutableNumber $fermatCoefficient */
42 3
            $fermatCoefficient = Numbers::make(Numbers::IMMUTABLE, $coefficient);
43
44 3
            if (!$fermatCoefficient->isEqual(0)) {
45 3
                $sanitizedCoefficients[$exponent] = $fermatCoefficient;
46
            }
47
        }
48
49 3
        $this->coefficients = $sanitizedCoefficients;
50
51 3
        $this->expression = function($x) use ($sanitizedCoefficients): ImmutableNumber {
52
            /** @var ImmutableNumber $value */
53 3
            $value = Numbers::makeZero();
54
55
            /** @var ImmutableNumber $xPart */
56 3
            $xPart = Numbers::makeOrDont(Numbers::IMMUTABLE, $x);
57
58 3
            foreach ($sanitizedCoefficients as $exponent => $coefficient) {
59 3
                if ($exponent == 0) {
60 3
                    $value = $value->add($coefficient);
61
                } else {
62 3
                    $term = $coefficient->multiply($xPart->pow($exponent));
63 3
                    $value = $value->add($term);
64
                }
65
            }
66
67 3
            return $value;
68
        };
69 3
    }
70
71
    /**
72
     * @param int|float|string|NumberInterface|DecimalInterface $x
73
     *
74
     * @return ImmutableNumber
75
     * @throws IntegrityConstraint
76
     */
77 3
    public function evaluateAt($x): ImmutableNumber
78
    {
79
        /** @var callable $answer */
80 3
        $answer = $this->expression;
81
82 3
        return $answer($x);
83
    }
84
85
    /**
86
     * @return FunctionInterface
87
     * @throws IntegrityConstraint
88
     */
89 1
    public function derivativeExpression(): FunctionInterface
90
    {
91 1
        $newCoefficients = [];
92
93
        /**
94
         * @var int             $exponent
95
         * @var ImmutableNumber $coefficient
96
         */
97 1
        foreach ($this->coefficients as $exponent => $coefficient) {
98 1
            if ($exponent == 0) {
99 1
                continue;
100
            }
101
102 1
            $newCoefficients[$exponent-1] = $coefficient->multiply($exponent);
103
        }
104
105 1
        return new PolynomialFunction($newCoefficients);
106
    }
107
108
    /**
109
     * @param int|float|string|NumberInterface|DecimalInterface $C
110
     *
111
     * @return FunctionInterface
112
     * @throws IntegrityConstraint
113
     */
114 1
    public function integralExpression($C = 0): FunctionInterface
115
    {
116 1
        $C = Numbers::make(Numbers::IMMUTABLE, $C);
117
118 1
        $newCoefficients = [];
119
120 1
        if (!$C->isEqual(0)) {
0 ignored issues
show
Bug introduced by
The method isEqual() does not exist on Samsara\Fermat\Types\Base\FractionInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Samsara\Fermat\Types\Base\FractionInterface. ( Ignorable by Annotation )

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

120
        if (!$C->/** @scrutinizer ignore-call */ isEqual(0)) {
Loading history...
Bug introduced by
The method isEqual() does not exist on Samsara\Fermat\Values\CartesianCoordinate. ( Ignorable by Annotation )

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

120
        if (!$C->/** @scrutinizer ignore-call */ isEqual(0)) {

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 isEqual() does not exist on Samsara\Fermat\Types\Base\CoordinateInterface. ( Ignorable by Annotation )

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

120
        if (!$C->/** @scrutinizer ignore-call */ isEqual(0)) {

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...
121 1
            $newCoefficients[0] = $C;
122
        }
123
124
        /**
125
         * @var int             $exponent
126
         * @var ImmutableNumber $coefficient
127
         */
128 1
        foreach ($this->coefficients as $exponent => $coefficient) {
129 1
            $newExponent = $exponent+1;
130
131 1
            $newCoefficients[$newExponent] = $coefficient->divide($newExponent);
132
        }
133
134 1
        return new PolynomialFunction($newCoefficients);
135
    }
136
137 3
    public function describeShape()
138
    {
139
140 3
        $shape = [];
141
142
        /**
143
         * @var int             $exponent
144
         * @var ImmutableNumber $coefficient
145
         */
146 3
        foreach ($this->coefficients as $exponent => $coefficient) {
147 3
            $shape[$exponent] = $coefficient->getValue();
148
        }
149
150 3
        return $shape;
151
152
    }
153
154
}