|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Samsara\Fermat\Provider; |
|
4
|
|
|
|
|
5
|
|
|
use Samsara\Fermat\Numbers; |
|
6
|
|
|
use Samsara\Fermat\Types\Base\NumberInterface; |
|
7
|
|
|
|
|
8
|
|
|
class SeriesProvider |
|
9
|
|
|
{ |
|
10
|
|
|
|
|
11
|
|
|
/** |
|
12
|
|
|
* Creates a series that evaluates the following: |
|
13
|
|
|
* |
|
14
|
|
|
* SUM[$startTerm -> infinity]( |
|
15
|
|
|
* $numerator($n) × $input^$exponent($n) |
|
16
|
|
|
* -------------------------------- |
|
17
|
|
|
* $denominator($n) |
|
18
|
|
|
* ) |
|
19
|
|
|
* |
|
20
|
|
|
* Where $n is the current term number, starting at $startTerm, and increasing by 1 each loop; where $numerator, |
|
21
|
|
|
* $exponent, and $denominator are callables that take the term number (as an int) as their only input, and give the |
|
22
|
|
|
* value of that section at that term number; and where $input is the x value being considered for the series. |
|
23
|
|
|
* |
|
24
|
|
|
* The function continues adding terms until a term has MORE leading zeros than the $precision setting. (That is, |
|
25
|
|
|
* until it adds zero to the total when considering significant digits.) |
|
26
|
|
|
* |
|
27
|
|
|
* @param NumberInterface $input |
|
28
|
|
|
* @param callable $numerator |
|
29
|
|
|
* @param callable $exponent |
|
30
|
|
|
* @param callable $denominator |
|
31
|
|
|
* @param int $startTermAt |
|
32
|
|
|
* @param int $precision |
|
33
|
|
|
* |
|
34
|
|
|
* @return NumberInterface |
|
35
|
|
|
*/ |
|
36
|
|
|
public static function maclaurinSeries( |
|
37
|
|
|
NumberInterface $input, // x value in series |
|
38
|
|
|
callable $numerator, // a function determining what the sign (+/-) at the nth term |
|
39
|
|
|
callable $exponent, // a function determining the exponent of x at the nth term |
|
40
|
|
|
callable $denominator, // a function determining the denominator at the nth term |
|
41
|
|
|
$startTermAt = 0, |
|
42
|
|
|
$precision = 10) |
|
43
|
|
|
{ |
|
44
|
|
|
|
|
45
|
|
|
$x = Numbers::makeZero(); |
|
46
|
|
|
$value = Numbers::make(Numbers::IMMUTABLE, $input->getValue()); |
|
47
|
|
|
|
|
48
|
|
|
$continue = true; |
|
49
|
|
|
$termNumber = $startTermAt; |
|
50
|
|
|
|
|
51
|
|
View Code Duplication |
while ($continue) { |
|
|
|
|
|
|
52
|
|
|
$term = Numbers::makeOne(); |
|
53
|
|
|
|
|
54
|
|
|
$term = $term->multiply($value->pow($exponent($termNumber))) |
|
55
|
|
|
->divide($denominator($termNumber)) |
|
56
|
|
|
->multiply($numerator($termNumber)); |
|
57
|
|
|
|
|
58
|
|
|
if ($term->numberOfLeadingZeros() >= $precision) { |
|
59
|
|
|
$continue = false; |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
$x = $x->add($term); |
|
63
|
|
|
|
|
64
|
|
|
$termNumber++; |
|
65
|
|
|
} |
|
66
|
|
|
|
|
67
|
|
|
return $x->roundToPrecision($precision); |
|
68
|
|
|
|
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
public static function genericTwoPartSeries( |
|
72
|
|
|
callable $part1, |
|
73
|
|
|
callable $part2, |
|
74
|
|
|
callable $exponent, |
|
75
|
|
|
$startTermAt = 0, |
|
76
|
|
|
$precision = 10) |
|
77
|
|
|
{ |
|
78
|
|
|
|
|
79
|
|
|
$x = Numbers::makeZero(); |
|
80
|
|
|
|
|
81
|
|
|
$continue = true; |
|
82
|
|
|
$termNumber = $startTermAt; |
|
83
|
|
|
|
|
84
|
|
View Code Duplication |
while ($continue) { |
|
|
|
|
|
|
85
|
|
|
$term = Numbers::makeOne(); |
|
86
|
|
|
|
|
87
|
|
|
$term = $term->multiply($part2($termNumber))->pow($exponent($termNumber)) |
|
88
|
|
|
->multiply($part1($termNumber)); |
|
89
|
|
|
|
|
90
|
|
|
if ($term->numberOfLeadingZeros() >= $precision) { |
|
91
|
|
|
$continue = false; |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
$x = $x->add($term); |
|
95
|
|
|
|
|
96
|
|
|
$termNumber++; |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
return $x->roundToPrecision($precision); |
|
100
|
|
|
|
|
101
|
|
|
} |
|
102
|
|
|
|
|
103
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.