Completed
Pull Request — dev (#40)
by Jordan
01:53
created

PolynomialFunction::derivativeExpression()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 3
nop 0
dl 0
loc 17
ccs 7
cts 7
cp 1
crap 3
rs 10
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 3
            $fermatCoefficient = Numbers::make(Numbers::IMMUTABLE, $coefficient);
42
43 3
            if (!$fermatCoefficient->isEqual(0)) {
0 ignored issues
show
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

43
            if (!$fermatCoefficient->/** @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\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

43
            if (!$fermatCoefficient->/** @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\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

43
            if (!$fermatCoefficient->/** @scrutinizer ignore-call */ isEqual(0)) {
Loading history...
44 3
                $sanitizedCoefficients[$exponent] = $fermatCoefficient;
45
            }
46
        }
47
48 3
        $this->coefficients = $sanitizedCoefficients;
49
50 3
        $this->expression = function($x) use ($sanitizedCoefficients): ImmutableNumber {
51
            /** @var ImmutableNumber $value */
52 3
            $value = Numbers::makeZero();
53
54
            /** @var ImmutableNumber $xPart */
55 3
            $xPart = Numbers::makeOrDont(Numbers::IMMUTABLE, $x);
56
57 3
            foreach ($sanitizedCoefficients as $exponent => $coefficient) {
58 3
                if ($exponent == 0) {
59 3
                    $value = $value->add($coefficient);
60
                } else {
61 3
                    $term = $coefficient->multiply($xPart->pow($exponent));
62 3
                    $value = $value->add($term);
63
                }
64
            }
65
66 3
            return $value;
67
        };
68 3
    }
69
70
    /**
71
     * @param int|float|string|NumberInterface|DecimalInterface $x
72
     *
73
     * @return ImmutableNumber
74
     * @throws IntegrityConstraint
75
     */
76 3
    public function evaluateAt($x): ImmutableNumber
77
    {
78
        /** @var callable $answer */
79 3
        $answer = $this->expression;
80
81 3
        return $answer($x);
82
    }
83
84
    /**
85
     * @return FunctionInterface
86
     * @throws IntegrityConstraint
87
     */
88 1
    public function derivativeExpression(): FunctionInterface
89
    {
90 1
        $newCoefficients = [];
91
92
        /**
93
         * @var int             $exponent
94
         * @var ImmutableNumber $coefficient
95
         */
96 1
        foreach ($this->coefficients as $exponent => $coefficient) {
97 1
            if ($exponent == 0) {
98 1
                continue;
99
            }
100
101 1
            $newCoefficients[$exponent-1] = $coefficient->multiply($exponent);
102
        }
103
104 1
        return new PolynomialFunction($newCoefficients);
105
    }
106
107
    /**
108
     * @param int|float|string|NumberInterface|DecimalInterface $C
109
     *
110
     * @return FunctionInterface
111
     * @throws IntegrityConstraint
112
     */
113 1
    public function integralExpression($C = 0): FunctionInterface
114
    {
115 1
        $C = Numbers::make(Numbers::IMMUTABLE, $C);
116
117 1
        $newCoefficients = [];
118
119 1
        if (!$C->isEqual(0)) {
120 1
            $newCoefficients[0] = $C;
121
        }
122
123
        /**
124
         * @var int             $exponent
125
         * @var ImmutableNumber $coefficient
126
         */
127 1
        foreach ($this->coefficients as $exponent => $coefficient) {
128 1
            $newExponent = $exponent+1;
129
130 1
            $newCoefficients[$newExponent] = $coefficient->divide($newExponent);
131
        }
132
133 1
        return new PolynomialFunction($newCoefficients);
134
    }
135
136 3
    public function describeShape()
137
    {
138
139 3
        $shape = [];
140
141
        /**
142
         * @var int             $exponent
143
         * @var ImmutableNumber $coefficient
144
         */
145 3
        foreach ($this->coefficients as $exponent => $coefficient) {
146 3
            $shape[$exponent] = $coefficient->getValue();
147
        }
148
149 3
        return $shape;
150
151
    }
152
153
}