diff --git a/src/Samsara/Fermat/Complex/Types/ComplexNumber.php b/src/Samsara/Fermat/Complex/Types/ComplexNumber.php index 12524489..0d152a75 100644 --- a/src/Samsara/Fermat/Complex/Types/ComplexNumber.php +++ b/src/Samsara/Fermat/Complex/Types/ComplexNumber.php @@ -159,9 +159,6 @@ public function asReal(): ImmutableDecimal|ImmutableFraction * @param string|int|float|Number $value * * @return bool - * @throws IncompatibleObjectState - * @throws IntegrityConstraint - * @throws OptionalExit */ public function isEqual(string|int|float|Number $value): bool { @@ -171,8 +168,6 @@ public function isEqual(string|int|float|Number $value): bool if (is_string($value) && !str_contains($value, 'i')) { return false; - } else { - $value = ComplexNumbers::make(ComplexNumbers::IMMUTABLE_COMPLEX, $value); } if ($value instanceof Number && !$value->isComplex()) { @@ -180,19 +175,9 @@ public function isEqual(string|int|float|Number $value): bool } if (!($value instanceof Number)) { - if (is_string($value)) { - try { - $value = static::makeFromString($value); - } catch (IntegrityConstraint) { - return false; - } - } elseif (is_array($value)) { - try { - $value = static::makeFromArray($value); - } catch (IntegrityConstraint) { - return false; - } - } else { + try { + $value = static::makeFromString($value); + } catch (\Exception) { return false; } } @@ -303,9 +288,9 @@ public static function makeFromArray(array $number, $scale = null, NumberBase $b public static function makeFromString(string $expression, $scale = null, NumberBase $base = NumberBase::Ten): static { if (str_contains($expression, '+')) { - [$part1, $part2] = explode('+', $expression); + $parts = explode('+', $expression); } elseif (str_contains($expression, '-')) { - [$part1, $part2] = explode('-', $expression); + $parts = explode('-', $expression); } else { throw new IntegrityConstraint( 'To make a complex number from a string, it must have both a real part and a complex part.', @@ -314,7 +299,7 @@ public static function makeFromString(string $expression, $scale = null, NumberB ); } - return static::makeFromArray([$part1, $part2], $scale, $base); + return static::makeFromArray($parts, $scale, $base); } /** diff --git a/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexHelperTrait.php b/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexHelperTrait.php index b5d7096b..f12ff83b 100644 --- a/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexHelperTrait.php +++ b/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexHelperTrait.php @@ -171,30 +171,25 @@ protected function helperPowPolar( /** * @param ImmutableComplexNumber|ImmutableDecimal|ImmutableFraction $thisNum * @param ImmutableDecimal $rotation - * @param int $scale * @return ImmutableDecimal[] * @throws IntegrityConstraint */ protected function helperPowPolarRotate( ImmutableComplexNumber|ImmutableDecimal|ImmutableFraction $thisNum, - ImmutableDecimal $rotation, - int $scale + ImmutableDecimal $rotation ): array { $rho = $thisNum->getDistanceFromOrigin(); $theta = $thisNum->getPolarAngle(); - if (!$rho->isEqual(0)) { - $rho = ArithmeticProvider::squareRoot($rho->getAsBaseTenRealNumber(), $scale); - } - + $rho = $rho->pow($rotation); $theta = $theta->multiply($rotation); $newPolar = new PolarCoordinate($rho, $theta); $newCartesian = $newPolar->asCartesian(); $newRealPart = $newCartesian->getAxis('x'); - $newImaginaryPart = $newCartesian->getAxis('y'); + $newImaginaryPart = $newCartesian->getAxis('y')->multiply('1i'); return [$newRealPart, $newImaginaryPart]; } @@ -214,13 +209,13 @@ protected function helperRootsPolarRotate( int $scale ): array { - $intScale = $scale + 2; + $intScale = $scale + $roots->asInt(); $rho = $thisNum->getDistanceFromOrigin(); $theta = $thisNum->getPolarAngle(); if (!$rho->isEqual(0)) { - $rho = ArithmeticProvider::squareRoot($rho->getAsBaseTenRealNumber(), $intScale); + $rho = $rho->pow((new ImmutableDecimal('1', $intScale))->setMode($this->getMode())->divide(3)); } $theta = $theta->divide($roots, $intScale); diff --git a/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexTrait.php b/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexTrait.php index b21cddf0..35250d5f 100644 --- a/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexTrait.php +++ b/src/Samsara/Fermat/Complex/Types/Traits/ArithmeticComplexTrait.php @@ -161,7 +161,7 @@ public function pow( [$thatRealPart, $thatImaginaryPart] = self::partSelector($thatNum, $thisNum, 0, $this->getMode(), $internalScale); if ($thatNum->isReal() && $thatNum->isNatural() && $thatNum->isPositive()) { - [$newRealPart, $newImaginaryPart] = $this->helperPowPolarRotate($thisNum, $thatNum, $scale); + [$newRealPart, $newImaginaryPart] = $this->helperPowPolarRotate($thisNum, $thatNum); } else { [$newRealPart, $newImaginaryPart] = $this->helperPowPolar($thatRealPart, $thatImaginaryPart, $internalScale); } @@ -208,7 +208,7 @@ public function sqrt( * @throws IntegrityConstraint * @throws OptionalExit */ - public function nthRoots(int|ImmutableDecimal $root, ?int $scale): array + public function nthRoots(int|ImmutableDecimal $root, ?int $scale = null): array { [$thisNum, $root] = $this->translateToObjects($root); @@ -226,7 +226,7 @@ public function nthRoots(int|ImmutableDecimal $root, ?int $scale): array for ($i=0;$root->isGreaterThan($i);$i++) { [$newRealPart, $newImaginaryPart] = $this->helperRootsPolarRotate($thisNum, $root, $i, $scale); - $roots[] = (new ImmutableComplexNumber($newRealPart, $newImaginaryPart))->setMode($this->getMode()); + $roots[] = (new ImmutableComplexNumber($newRealPart, $newImaginaryPart))->setMode($this->getMode())->roundToScale($scale); } return $roots; diff --git a/tests/Samsara/Fermat/Complex/Values/ArithmeticAutoTest.php b/tests/Samsara/Fermat/Complex/Values/ArithmeticAutoTest.php index 55e4442c..61a36575 100644 --- a/tests/Samsara/Fermat/Complex/Values/ArithmeticAutoTest.php +++ b/tests/Samsara/Fermat/Complex/Values/ArithmeticAutoTest.php @@ -528,6 +528,8 @@ public function powerImmutableComplexMediumProvider(): array 'IComplex (3+3i)^(0)' => [$a, $zero, '1', ImmutableDecimal::class], 'IComplex (3+3i)^(3i)' => [$a, $threeI, '-0.0348768474-0.088129998i', ImmutableComplexNumber::class], 'IComplex (3i)^(3+3i)' => [$threeI, $a, '-0.0372635883+0.2396692999i', ImmutableComplexNumber::class], + 'IComplex (3+3i)^(3)' => [$a, $three, '-54+54i', ImmutableComplexNumber::class], + 'IComplex (3)^(3+3i)' => [$three, $a, '-26.6794540328-4.1480998674i', ImmutableComplexNumber::class], 'IComplex (1+0.0000000001i)^(3+3i)' => [$g, $a, '0.9999999997+0.0000000003i', ImmutableComplexNumber::class], 'IComplex (0.0000000001+1i)^(3+3i)' => [$h, $a, '-0.008983291i', ImmutableDecimal::class], 'IComplex (1+0.000000000001i)^(3+3i)' => [$i, $a, '0.999999999997+0.000000000003i', ImmutableComplexNumber::class], @@ -688,4 +690,71 @@ public function testSqrtLarge(ComplexNumber|Decimal $a, string $expected, ?strin } } + + + /* + * nthRoot() + */ + + public function nthRootImmutableComplexMediumProvider(): array + { + $three = new ImmutableDecimal('3'); + $threeI = new ImmutableDecimal('3i'); + $negThree = new ImmutableDecimal('-3'); + $negThreeI = new ImmutableDecimal('-3i'); + $zero = new ImmutableDecimal('0'); + $zeroI = new ImmutableDecimal('0i'); + $one = new ImmutableDecimal('1'); + $oneI = new ImmutableDecimal('1i'); + $tenScale = new ImmutableDecimal('0.0000000001'); + $tenScaleI = new ImmutableDecimal('0.0000000001i'); + $twelveScale = new ImmutableDecimal('0.000000000001'); + $twelveScaleI = new ImmutableDecimal('0.000000000001i'); + + $a = new ImmutableComplexNumber($three, $threeI); + $b = new ImmutableComplexNumber($negThree, $negThreeI); + $c = new ImmutableComplexNumber($three, $negThreeI); + $d = new ImmutableComplexNumber($negThree, $threeI); + $g = new ImmutableComplexNumber($one, $tenScaleI); + $h = new ImmutableComplexNumber($tenScale, $oneI); + $i = new ImmutableComplexNumber($one, $twelveScaleI); + $j = new ImmutableComplexNumber($twelveScale, $oneI); + $k = new ImmutableComplexNumber($one, $zeroI); + $l = new ImmutableComplexNumber($zero, $oneI); + + return [ + 'IComplex (3+3i)^(1/3)' => [ + $a, + $three, + [ + '1.5637087354+0.4189944928i', + '-1.1447142426+1.1447142426i', + '-0.4189944928-1.5637087354i', + ] + ], + //'IComplex (-3-3i)^(1/3)' => [$b, $three, '0.7882387605-1.902976706i', ImmutableComplexNumber::class], + //'IComplex (3-3i)^(1/3)' => [$c, $three, '1.902976706-0.7882387605i', ImmutableComplexNumber::class], +// 'IComplex (-3+3i)^(1/3)' => [$d, $three, '0.7882387605+1.902976706i', ImmutableComplexNumber::class], +// 'IComplex (1+0.0000000001i)^(1/3)' => [$g, $three, '1', ImmutableDecimal::class], +// 'IComplex (0.0000000001+1i)^(1/3)' => [$h, $three, '0.7071067812+0.7071067812i', ImmutableComplexNumber::class], +// 'IComplex (1+0.000000000001i)^(1/3)' => [$i, $three, '1', ImmutableDecimal::class], +// 'IComplex (0.000000000001+1i)^(1/3)' => [$j, $three, '0.707106781187+0.707106781186i', ImmutableComplexNumber::class], +// 'IComplex (1+0i)^(1/3)' => [$k, $three, '1', ImmutableDecimal::class], +// 'IComplex (0+1i)^(1/3)' => [$l, $three, '0.7071067812+0.7071067812i', ImmutableComplexNumber::class], + ]; + } + + /** + * @medium + * @dataProvider nthRootImmutableComplexMediumProvider + */ + public function testNthRoots(ComplexNumber $a, ImmutableDecimal $b, array $expected) + { + $answers = $a->nthRoots($b); + + foreach ($answers as $i => $answer) { + $this->assertEquals($expected[$i], $answer->getValue()); + } + } + } \ No newline at end of file diff --git a/tests/Samsara/Fermat/Complex/Values/ImmutableComplexNumberTest.php b/tests/Samsara/Fermat/Complex/Values/ImmutableComplexNumberTest.php index 9b8f612a..3870b0fd 100644 --- a/tests/Samsara/Fermat/Complex/Values/ImmutableComplexNumberTest.php +++ b/tests/Samsara/Fermat/Complex/Values/ImmutableComplexNumberTest.php @@ -5,6 +5,8 @@ namespace Samsara\Fermat\Complex\Values; use PHPUnit\Framework\TestCase; +use Samsara\Exceptions\SystemError\LogicalError\IncompatibleObjectState; +use Samsara\Fermat\Coordinates\Values\PolarCoordinate; use Samsara\Fermat\Core\Values\ImmutableDecimal; /** @@ -78,4 +80,79 @@ public function testAbsValue() } + public function testAsPolar() + { + + $complex = self::$complexOneTwo; + + $this->assertEquals(PolarCoordinate::class, get_class($complex->asPolar())); + $this->assertEquals('2.23606797749979', $complex->asPolar()->getDistanceFromOrigin()->getValue()); + $this->assertEquals('1.107148717794', $complex->asPolar()->getPolarAngle()->getValue()); + + } + + public function testGetAsBaseTenRealNumber() + { + $complex = self::$complexOneTwo; + + $this->assertEquals('2.23606797749979', $complex->getAsBaseTenRealNumber()); + } + + public function testIsFunctions() + { + $complex = self::$complexOneTwo; + + // isImaginary + $this->assertFalse($complex->isImaginary()); + + // isEqual + $this->assertFalse($complex->isEqual('1')); + $this->assertFalse($complex->isEqual(new ImmutableDecimal(1))); + $this->assertFalse($complex->isEqual('1+3i')); + $this->assertFalse($complex->isEqual('1+3i+6')); + $this->assertFalse($complex->isEqual('2i')); + $this->assertFalse($complex->isEqual('2i+4i')); + $this->assertTrue($complex->isEqual('1+2i')); + $this->assertTrue($complex->isEqual(self::$complexOneTwo)); + } + + public function testExceptionInequality1() + { + $complex = self::$complexOneTwo; + + $this->expectException(IncompatibleObjectState::class); + $complex->isGreaterThan('1'); + } + + public function testExceptionInequality2() + { + $complex = self::$complexOneTwo; + + $this->expectException(IncompatibleObjectState::class); + $complex->isGreaterThanOrEqualTo('1'); + } + + public function testExceptionInequality3() + { + $complex = self::$complexOneTwo; + + $this->expectException(IncompatibleObjectState::class); + $complex->isLessThan('1'); + } + + public function testExceptionInequality4() + { + $complex = self::$complexOneTwo; + + $this->expectException(IncompatibleObjectState::class); + $complex->isLessThanOrEqualTo('1'); + } + + public function testAsComplex() + { + $complex = self::$complexOneTwo; + + $this->assertEquals(ImmutableComplexNumber::class, get_class($complex->asComplex())); + } + } \ No newline at end of file