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
|
1 |
|
public function __construct(array $coefficients) |
20
|
|
|
{ |
21
|
1 |
|
parent::__construct(Expression::POLYNOMIAL); |
22
|
|
|
|
23
|
1 |
|
foreach ($coefficients as $exponent => $coefficient) { |
24
|
1 |
|
if (!is_int($exponent)) { |
25
|
|
|
throw new IntegrityConstraint( |
26
|
|
|
'Keys in the $coefficients array must be integers', |
27
|
|
|
'Only use integer keys for the $coefficients array', |
28
|
|
|
'The key '.$exponent.' was found in the $coefficients array; an integer was expected' |
29
|
|
|
); |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
if ( |
33
|
1 |
|
!is_int($coefficient) && |
34
|
1 |
|
!is_float($coefficient) && |
35
|
1 |
|
!is_numeric($coefficient) && |
36
|
1 |
|
!($coefficient instanceof DecimalInterface) && |
37
|
1 |
|
!($coefficient instanceof NumberInterface) |
38
|
|
|
) { |
39
|
|
|
throw new IntegrityConstraint( |
40
|
|
|
'Values for coefficients must be valid for an ImmutableNumber constructor', |
41
|
|
|
'Only give values which can be used for an ImmutableNumber constructor', |
42
|
|
|
'The coefficient '.$coefficient.' is not valid for an ImmutableNumber constructor' |
43
|
|
|
); |
44
|
|
|
} |
45
|
|
|
} |
46
|
|
|
|
47
|
1 |
|
$this->coefficients = $coefficients; |
48
|
|
|
|
49
|
|
|
$this->expression = function($x) use ($coefficients): ImmutableNumber { |
50
|
|
|
/** @var ImmutableNumber $value */ |
51
|
1 |
|
$value = Numbers::makeZero(); |
52
|
|
|
|
53
|
|
|
/** @var ImmutableNumber $xPart */ |
54
|
1 |
|
$xPart = Numbers::makeOrDont(Numbers::IMMUTABLE, $x); |
55
|
|
|
|
56
|
1 |
|
foreach ($coefficients as $exponent => $coefficient) { |
57
|
|
|
/** @var ImmutableNumber $term */ |
58
|
1 |
|
$term = Numbers::makeOrDont(Numbers::IMMUTABLE, $coefficient); |
59
|
|
|
|
60
|
1 |
|
if ($term->isEqual(0)) { |
61
|
1 |
|
continue; |
62
|
|
|
} |
63
|
|
|
|
64
|
1 |
|
if ($exponent == 0) { |
65
|
1 |
|
$value = $value->add($term); |
66
|
|
|
} else { |
67
|
1 |
|
$term = $term->multiply($xPart->pow($exponent)); |
68
|
1 |
|
$value = $value->add($term); |
69
|
|
|
} |
70
|
|
|
} |
71
|
|
|
|
72
|
1 |
|
return $value; |
73
|
|
|
}; |
74
|
1 |
|
} |
75
|
|
|
|
76
|
1 |
|
public function evaluateAt($x): NumberInterface |
77
|
|
|
{ |
78
|
1 |
|
$answer = $this->expression; |
79
|
|
|
|
80
|
1 |
|
return $answer($x); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
public function derivativeExpression(): ExpressionInterface |
84
|
|
|
{ |
85
|
|
|
// TODO: Implement derivativeExpression() method. |
86
|
|
|
} |
|
|
|
|
87
|
|
|
|
88
|
|
|
public function integralExpression(): ExpressionInterface |
89
|
|
|
{ |
90
|
|
|
// TODO: Implement integralExpression() method. |
91
|
|
|
} |
|
|
|
|
92
|
|
|
|
93
|
|
|
} |
For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example: