Skip to content
This repository was archived by the owner on Dec 27, 2023. It is now read-only.

Commit 4495d4d

Browse files
committed
Merge pull request #46 from codisart/add-arctan-method
[TECH] Add the arctan method. Thanks to @codisart .
2 parents ec108cd + cc56a44 commit 4495d4d

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

src/Decimal.php

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,35 @@ public function arccos($scale = null)
848848
)->round($scale);
849849
}
850850

851+
/**
852+
* Calculates the arctangente of this with the highest possible accuracy
853+
*
854+
* @param integer $scale
855+
* @return Decimal
856+
*/
857+
public function arctan($scale = null)
858+
{
859+
$piOverFour = DecimalConstants::pi()->div(Decimal::fromInteger(4), $scale + 2)->round($scale);
860+
861+
if ($this->round($scale)->isZero()) {
862+
return DecimalConstants::zero();
863+
}
864+
if ($this->round($scale)->equals(DecimalConstants::one())) {
865+
return $piOverFour;
866+
}
867+
if ($this->round($scale)->equals(DecimalConstants::negativeOne())) {
868+
return DecimalConstants::negativeOne()->mul($piOverFour);
869+
}
870+
871+
$scale = ($scale === null) ? 32 : $scale;
872+
873+
return self::simplePowerSerie(
874+
$this,
875+
DecimalConstants::zero(),
876+
$scale
877+
)->round($scale);
878+
}
879+
851880
/**
852881
* Returns exp($this), said in other words: e^$this .
853882
*
@@ -905,7 +934,7 @@ private static function factorialSerie (Decimal $x, Decimal $firstTerm, callable
905934

906935

907936
/**
908-
* Internal method used to compute arcsine *
937+
* Internal method used to compute arcsine and arcosine
909938
*
910939
* @param Decimal $x
911940
* @param Decimal $firstTerm
@@ -953,6 +982,44 @@ private static function powerSerie (Decimal $x, Decimal $firstTerm, $scale)
953982
return $approx->round($scale);
954983
}
955984

985+
/**
986+
* Internal method used to compute arctan and arccotan
987+
*
988+
* @param Decimal $x
989+
* @param Decimal $firstTerm
990+
* @param $scale
991+
* @return Decimal
992+
*/
993+
private static function simplePowerSerie (Decimal $x, Decimal $firstTerm, $scale)
994+
{
995+
$approx = $firstTerm;
996+
$change = InfiniteDecimal::getPositiveInfinite();
997+
998+
$xPowerN = DecimalConstants::One(); // Calculates x^n
999+
$sign = DecimalConstants::One(); // Calculates a_n
1000+
1001+
for ($i = 1; !$change->floor($scale + 2)->isZero(); $i++) {
1002+
$xPowerN = $xPowerN->mul($x);
1003+
1004+
if ($i % 2 === 0) {
1005+
$factorN = DecimalConstants::zero();
1006+
} else {
1007+
if ($i % 4 === 1) {
1008+
$factorN = DecimalConstants::one()->div(Decimal::fromInteger($i), $scale + 2);
1009+
} else {
1010+
$factorN = DecimalConstants::negativeOne()->div(Decimal::fromInteger($i), $scale + 2);
1011+
}
1012+
}
1013+
1014+
if (!$factorN->isZero()) {
1015+
$change = $factorN->mul($xPowerN, $scale + 2);
1016+
$approx = $approx->add($change, $scale + 2);
1017+
}
1018+
}
1019+
1020+
return $approx->round($scale);
1021+
}
1022+
9561023
/**
9571024
* Calculates the tangent of this method with the highest possible accuracy
9581025
* Note that accuracy is limited by the accuracy of predefined PI;

tests/Decimal/DecimalArctanTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
use Litipk\BigNumbers\Decimal as Decimal;
4+
5+
/**
6+
* @group arctan
7+
*/
8+
class DecimalArctanTest extends PHPUnit_Framework_TestCase
9+
{
10+
public function arctanProvider() {
11+
// Some values provided by wolframalpha
12+
return [
13+
['0.154', '0.15279961393666', 14],
14+
['0', '0', 17],
15+
['-1', '-0.78539816339744831', 17],
16+
];
17+
}
18+
19+
/**
20+
* @dataProvider arctanProvider
21+
*/
22+
public function testSimple($nr, $answer, $digits)
23+
{
24+
$x = Decimal::fromString($nr);
25+
$arctanX = $x->arctan($digits);
26+
27+
$this->assertTrue(
28+
Decimal::fromString($answer)->equals($arctanX),
29+
"The answer must be " . $answer . ", but was " . $arctanX
30+
);
31+
}
32+
33+
}

0 commit comments

Comments
 (0)