ComplexTest.php 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082
  1. <?php
  2. namespace MathPHP\Tests\Number;
  3. use MathPHP\Number\Complex;
  4. use MathPHP\Exception;
  5. use MathPHP\Number\ObjectArithmetic;
  6. class ComplexTest extends \PHPUnit\Framework\TestCase
  7. {
  8. /**
  9. * @test Interfaces
  10. */
  11. public function testObjectArithmeticInterface()
  12. {
  13. // Given
  14. $c = new Complex(1, 2);
  15. // Then
  16. $this->assertInstanceOf(ObjectArithmetic::class, $c);
  17. }
  18. public function testZeroValue()
  19. {
  20. // Given
  21. $c = Complex::createZeroValue();
  22. // Then
  23. $this->assertEquals(0, $c->r);
  24. $this->assertEquals(0, $c->i);
  25. }
  26. /**
  27. * @test __toString returns the proper string representation of a complex number
  28. * @dataProvider dataProviderForToString
  29. * @param number $r
  30. * @param number $i
  31. * @param string $expected
  32. */
  33. public function testToString($r, $i, string $expected)
  34. {
  35. // Given
  36. $complex = new Complex($r, $i);
  37. // When
  38. $string = $complex->__toString();
  39. // Then
  40. $this->assertEquals($expected, $string);
  41. $this->assertEquals($expected, (string) $complex);
  42. }
  43. public function dataProviderForToString(): array
  44. {
  45. return [
  46. [0, 0, '0'],
  47. [1, 0, '1'],
  48. [-1, 0, '-1'],
  49. [0, 1, '1i'],
  50. [0, -1, '-1i'],
  51. [1, 1, '1 + 1i'],
  52. [1, 2, '1 + 2i'],
  53. [2, 1, '2 + 1i'],
  54. [2, 2, '2 + 2i'],
  55. [1, -1, '1 - 1i'],
  56. [1, -2, '1 - 2i'],
  57. [2, -1, '2 - 1i'],
  58. [2, -2, '2 - 2i'],
  59. [-1, 1, '-1 + 1i'],
  60. [-1, 2, '-1 + 2i'],
  61. [-2, 1, '-2 + 1i'],
  62. [-2, 2, '-2 + 2i'],
  63. [-1, -1, '-1 - 1i'],
  64. [-1, -2, '-1 - 2i'],
  65. [-2, -1, '-2 - 1i'],
  66. [-2, -2, '-2 - 2i'],
  67. ];
  68. }
  69. /**
  70. * @test __get returns r and i
  71. */
  72. public function testGet()
  73. {
  74. // Given
  75. $r = 1;
  76. $i = 2;
  77. $complex = new Complex($r, $i);
  78. // Then
  79. $this->assertEquals($r, $complex->r);
  80. $this->assertEquals($i, $complex->i);
  81. }
  82. /**
  83. * @test __get throws an Exception\BadParameterException if a property other than r or i is attempted
  84. */
  85. public function testGetException()
  86. {
  87. // Given
  88. $r = 1;
  89. $i = 2;
  90. $complex = new Complex($r, $i);
  91. // Then
  92. $this->expectException(Exception\BadParameterException::class);
  93. // When
  94. $z = $complex->z;
  95. }
  96. /**
  97. * @test complexConjugate returns the expected Complex number
  98. * @dataProvider dataProviderForComplexConjugate
  99. * @param number $r
  100. * @param number $i
  101. */
  102. public function testComplexConjugate($r, $i)
  103. {
  104. // Given
  105. $c = new Complex($r, $i);
  106. // When
  107. $cc = $c->complexConjugate();
  108. // Then
  109. $this->assertEquals($c->r, $cc->r);
  110. $this->assertEquals($c->i, -1 * $cc->i);
  111. }
  112. public function dataProviderForComplexConjugate(): array
  113. {
  114. return [
  115. [0, 0],
  116. [1, 0],
  117. [0, 1],
  118. [1, 1],
  119. [1, 2],
  120. [3, 7],
  121. ];
  122. }
  123. /**
  124. * @test abs returns the expected value
  125. * @dataProvider dataProviderForAbs
  126. * @param number $r
  127. * @param number $i
  128. * @param number $expected
  129. */
  130. public function testAbs($r, $i, $expected)
  131. {
  132. // Given
  133. $c = new Complex($r, $i);
  134. // When
  135. $abs = $c->abs();
  136. // Then
  137. $this->assertEquals($expected, $abs);
  138. }
  139. public function dataProviderForAbs(): array
  140. {
  141. return [
  142. [0, 0, 0],
  143. [1, 0, 1],
  144. [0, 1, 1],
  145. [1, 2, \sqrt(5)],
  146. [2, 1, \sqrt(5)],
  147. [2, 2, \sqrt(8)],
  148. [-1, 0, 1],
  149. [0, -1, 1],
  150. [-1, 2, \sqrt(5)],
  151. [2, -1, \sqrt(5)],
  152. [-2, -2, \sqrt(8)],
  153. ];
  154. }
  155. /**
  156. * @test arg returns the expected value
  157. * @dataProvider dataProviderForArg
  158. * @param number $r
  159. * @param number $i
  160. * @param number $expected
  161. */
  162. public function testArg($r, $i, $expected)
  163. {
  164. // Given
  165. $c = new Complex($r, $i);
  166. // When
  167. $arg = $c->arg();
  168. // Then
  169. $this->assertEqualsWithDelta($expected, $arg, 0.00000001);
  170. }
  171. public function dataProviderForArg(): array
  172. {
  173. return [
  174. [0, 1, \M_PI / 2],
  175. [0, -1, \M_PI / -2],
  176. [1, 1, 0.7853981633974483],
  177. [2, 2, 0.7853981633974483],
  178. [3, 3, 0.7853981633974483],
  179. [1, 2, 1.1071487177940904],
  180. [2, 1, 0.4636476090008061],
  181. [3, 1.4, 0.4366271598135413],
  182. [\M_PI, 1, 0.30816907111598496],
  183. [1, \M_PI, 1.2626272556789115],
  184. [-1, 1, 2.356194490192345],
  185. [1, -1, -0.78539816],
  186. [-1, -1, -2.35619449],
  187. ];
  188. }
  189. /**
  190. * @test sqrt returns the expected positive Complex root
  191. * @dataProvider dataProviderForSqrt
  192. * @param number $r
  193. * @param number $i
  194. * @param number $expected_r
  195. * @param number $expected_i
  196. */
  197. public function testSqrt($r, $i, $expected_r, $expected_i)
  198. {
  199. // Given
  200. $c = new Complex($r, $i);
  201. // When
  202. $sqrt = $c->sqrt();
  203. // Then
  204. $this->assertEqualsWithDelta($expected_r, $sqrt->r, 0.00001);
  205. $this->assertEqualsWithDelta($expected_i, $sqrt->i, 0.00001);
  206. }
  207. public function dataProviderForSqrt(): array
  208. {
  209. return [
  210. [8, -6, 3, -1],
  211. [9, 4, \sqrt((9 + \sqrt(97)) / 2), 2 * (sqrt(2 / (9 + \sqrt(97))))],
  212. [-4, -6, 1.2671, -2.3676],
  213. [0, 9, 2.1213203, 2.1213203],
  214. [10, -6, 3.2910412, -0.9115656],
  215. [-4, 0, 0, 2],
  216. [-3, 0, 0, 1.7320508],
  217. [-2, 0, 0, 1.4142136],
  218. [-1, 0, 0, 1],
  219. [0, 0, 0, 0],
  220. ];
  221. }
  222. /**
  223. * @test roots returns the expected array of two Complex roots
  224. * @dataProvider dataProviderForRoots
  225. * @param number $r
  226. * @param number $i
  227. * @param array $z₁
  228. * @param array $z₂
  229. */
  230. public function testRoots($r, $i, array $z₁, array $z₂)
  231. {
  232. // Given
  233. $c = new Complex($r, $i);
  234. // When
  235. $roots = $c->roots();
  236. // Then
  237. $this->assertEqualsWithDelta($z₁['r'], $roots[0]->r, 0.00001);
  238. $this->assertEqualsWithDelta($z₁['i'], $roots[0]->i, 0.00001);
  239. $this->assertEqualsWithDelta($z₂['r'], $roots[1]->r, 0.00001);
  240. $this->assertEqualsWithDelta($z₂['i'], $roots[1]->i, 0.00001);
  241. }
  242. public function dataProviderForRoots(): array
  243. {
  244. return [
  245. [8, -6, ['r' => 3, 'i' => -1], ['r' => -3, 'i' => 1]],
  246. [9, 4, ['r' => \sqrt((9 + \sqrt(97)) / 2), 'i' => 2 * (sqrt(2 / (9 + \sqrt(97))))], ['r' => -sqrt((9 + \sqrt(97)) / 2), 'i' => -2 * (sqrt(2 / (9 + \sqrt(97))))]],
  247. [-4, -6, ['r' => 1.2671, 'i' => -2.3676], ['r' => -1.2671, 'i' => 2.3676]],
  248. [0, 9, ['r' => 2.1213203, 'i' => 2.1213203], ['r' => -2.1213203, 'i' => -2.1213203]],
  249. [10, -6, ['r' => 3.2910412, 'i' => -0.9115656], ['r' => -3.2910412, 'i' => 0.9115656]],
  250. [3, 3, ['r' => 1.90298, 'i' => 0.78824], ['r' => -1.90298, 'i' => -0.78824]],
  251. [-4, 0, ['r' => 0, 'i' => 2], ['r' => 0, 'i' => -2]],
  252. [-3, 0, ['r' => 0, 'i' => 1.7320508], ['r' => 0, 'i' => -1.7320508]],
  253. [-2, 0, ['r' => 0, 'i' => 1.4142136], ['r' => 0, 'i' => -1.4142136]],
  254. [-1, 0, ['r' => 0, 'i' => 1], ['r' => 0, 'i' => -1]],
  255. [0, 0, ['r' => 0, 'i' => 0], ['r' => 0, 'i' => -0]],
  256. ];
  257. }
  258. /**
  259. * @test negate returns the expected complex number with signs negated
  260. * @dataProvider dataProviderForNegate
  261. * @param number $r₁
  262. * @param number $i₁
  263. * @param number $r₂
  264. * @param number $i₂
  265. */
  266. public function testNegate($r₁, $i₁, $r₂, $i₂)
  267. {
  268. // Given
  269. $c = new Complex($r₁, $i₁);
  270. $expected = new Complex($r₂, $i₂);
  271. // When
  272. $negated = $c->negate();
  273. // Then
  274. $this->assertTrue($negated->equals($expected));
  275. $this->assertEquals($expected->r, $negated->r);
  276. $this->assertEquals($expected->i, $negated->i);
  277. }
  278. public function dataProviderForNegate(): array
  279. {
  280. return [
  281. [0, 0, 0, 0],
  282. [1, 0, -1, 0],
  283. [0, 1, 0, -1],
  284. [1, 2, -1, -2],
  285. [3, 4, -3, -4],
  286. [-4, -5, 4, 5],
  287. [-6, 3, 6, -3],
  288. ];
  289. }
  290. /**
  291. * @test polarForm returns the expected complex number
  292. * @dataProvider dataProviderForPolarForm
  293. * @param number $r
  294. * @param number $i
  295. * @param number $expectedR
  296. * @param number $expectedθ
  297. */
  298. public function testPolarForm($r, $i, $expectedR, $expectedθ)
  299. {
  300. // Given
  301. $c = new Complex($r, $i);
  302. // When
  303. [$polarR, $polarθ] = $c->polarForm();
  304. // Then
  305. $this->assertEqualsWithDelta($expectedR, $polarR, 0.00001);
  306. $this->assertEqualsWithDelta($expectedθ, $polarθ, 0.00001);
  307. }
  308. /**
  309. * Test data created with: http://www.analyzemath.com/Calculators/complex_polar_exp.html
  310. * Python: cmath.polar(complex(5, 2))
  311. * @return array
  312. */
  313. public function dataProviderForPolarForm(): array
  314. {
  315. return [
  316. [5, 2, 5.385164807134504, 0.3805063771123649],
  317. [49.90, 25.42, 56.00166426098424, 0.4711542560514266],
  318. [-1, -1, 1.4142135623730951, -2.356194490192345],
  319. [1, 0, 1, 0],
  320. [0, 1, 1, 1.5707963267948966],
  321. [0, 0, 0, 0],
  322. [\M_PI, 2, 3.724191778237173, 0.5669115049410094],
  323. [8, 9, 12.041594578792296, 0.844153986113171],
  324. [814, -54, 815.7891884549587, -0.06624200592698481],
  325. [-5, -3, 5.830951894845301, -2.601173153319209],
  326. ];
  327. }
  328. /**
  329. * @test exp returns the expected complex number
  330. * @dataProvider dataProviderForExp
  331. * @param number $r₁
  332. * @param number $i₁
  333. * @param number $r₂
  334. * @param number $i₂
  335. */
  336. public function testExp($r₁, $i₁, $r₂, $i₂)
  337. {
  338. // Given
  339. $c = new Complex($r₁, $i₁);
  340. $expected = new Complex($r₂, $i₂);
  341. // When
  342. $exp = $c->exp();
  343. // Then
  344. $this->assertEqualsWithDelta($expected->r, $exp->r, 0.00001);
  345. $this->assertEqualsWithDelta($expected->i, $exp->i, 0.00001);
  346. }
  347. /**
  348. * Test data created from wolfram alpha: example: https://www.wolframalpha.com/input/?i=e%5E%281%2B2*i%29
  349. * @return array
  350. */
  351. public function dataProviderForExp(): array
  352. {
  353. return [
  354. [0, \pi(), -1, 0],
  355. [1, 2, -1.13120438375681363843125525551079471062886799582652575021772191, 2.47172667200481892761693089355166453273619036924100818420075883],
  356. [5, 0, \exp(5), 0],
  357. ];
  358. }
  359. /**
  360. * @test add of two complex numbers returns the expected complex number
  361. * @dataProvider dataProviderForAdd
  362. * @param array $complex1
  363. * @param array $complex2
  364. * @param array $expected
  365. */
  366. public function testAdd(array $complex1, array $complex2, array $expected)
  367. {
  368. // Given
  369. $c1 = new Complex($complex1['r'], $complex1['i']);
  370. $c2 = new Complex($complex2['r'], $complex2['i']);
  371. // When
  372. $result = $c1->add($c2);
  373. // Then
  374. $this->assertEquals($expected['r'], $result->r);
  375. $this->assertEquals($expected['i'], $result->i);
  376. }
  377. public function dataProviderForAdd(): array
  378. {
  379. return [
  380. [
  381. ['r' => 3, 'i' => 2],
  382. ['r' => 4, 'i' => -3],
  383. ['r' => 7, 'i' => -1],
  384. ],
  385. [
  386. ['r' => 0, 'i' => 0],
  387. ['r' => 4, 'i' => -3],
  388. ['r' => 4, 'i' => -3],
  389. ],
  390. [
  391. ['r' => -3, 'i' => -2],
  392. ['r' => 4, 'i' => 3],
  393. ['r' => 1, 'i' => 1],
  394. ],
  395. [
  396. ['r' => 7, 'i' => 6],
  397. ['r' => 4, 'i' => 4],
  398. ['r' => 11, 'i' => 10],
  399. ],
  400. ];
  401. }
  402. /**
  403. * @test add of real numbers returns the expected complex number
  404. * @dataProvider dataProviderForAddReal
  405. */
  406. public function testAddReal($complex, $real, $expected)
  407. {
  408. // Given
  409. $c = new Complex($complex['r'], $complex['i']);
  410. // When
  411. $result = $c->add($real);
  412. // Then
  413. $this->assertEquals($expected['r'], $result->r);
  414. $this->assertEquals($expected['i'], $result->i);
  415. }
  416. public function dataProviderForAddReal()
  417. {
  418. return [
  419. [
  420. ['r' => 3, 'i' => 2],
  421. 5,
  422. ['r' => 8, 'i' => 2],
  423. ],
  424. [
  425. ['r' => 0, 'i' => 0],
  426. 5,
  427. ['r' => 5, 'i' => 0],
  428. ],
  429. [
  430. ['r' => 3, 'i' => 2],
  431. -2,
  432. ['r' => 1, 'i' => 2],
  433. ],
  434. ];
  435. }
  436. /**
  437. * @test subtract of two complex numbers returns the expected complex number
  438. * @dataProvider dataProviderForSubtract
  439. * @param array $complex1
  440. * @param array $complex2
  441. * @param array $expected
  442. */
  443. public function testSubtract(array $complex1, array $complex2, array $expected)
  444. {
  445. // Given
  446. $c1 = new Complex($complex1['r'], $complex1['i']);
  447. $c2 = new Complex($complex2['r'], $complex2['i']);
  448. // When
  449. $result = $c1->subtract($c2);
  450. // Then
  451. $this->assertEquals($expected['r'], $result->r);
  452. $this->assertEquals($expected['i'], $result->i);
  453. }
  454. public function dataProviderForSubtract(): array
  455. {
  456. return [
  457. [
  458. ['r' => 3, 'i' => 2],
  459. ['r' => 4, 'i' => -3],
  460. ['r' => -1, 'i' => 5],
  461. ],
  462. [
  463. ['r' => 3, 'i' => 2],
  464. ['r' => 4, 'i' => -3],
  465. ['r' => -1, 'i' => 5],
  466. ],
  467. [
  468. ['r' => 0, 'i' => 0],
  469. ['r' => 4, 'i' => -3],
  470. ['r' => -4, 'i' => 3],
  471. ],
  472. [
  473. ['r' => -3, 'i' => -2],
  474. ['r' => 4, 'i' => 3],
  475. ['r' => -7, 'i' => -5],
  476. ],
  477. [
  478. ['r' => 7, 'i' => 6],
  479. ['r' => 4, 'i' => 4],
  480. ['r' => 3, 'i' => 2],
  481. ],
  482. ];
  483. }
  484. /**
  485. * @test subtract of real numbers returns the expected complex number
  486. * @dataProvider dataProviderForSubtractReal
  487. */
  488. public function testSubtractReal($complex, $real, $expected)
  489. {
  490. // Given
  491. $c = new Complex($complex['r'], $complex['i']);
  492. // When
  493. $result = $c->subtract($real);
  494. // Then
  495. $this->assertEquals($expected['r'], $result->r);
  496. $this->assertEquals($expected['i'], $result->i);
  497. }
  498. public function dataProviderForSubtractReal(): array
  499. {
  500. return [
  501. [
  502. ['r' => 3, 'i' => 2],
  503. 5,
  504. ['r' => -2, 'i' => 2],
  505. ],
  506. [
  507. ['r' => 0, 'i' => 0],
  508. 5,
  509. ['r' => -5, 'i' => 0],
  510. ],
  511. [
  512. ['r' => 3, 'i' => 2],
  513. -2,
  514. ['r' => 5, 'i' => 2],
  515. ],
  516. ];
  517. }
  518. /**
  519. * @test multiply of two complex numbers returns the expected complex number
  520. * @dataProvider dataProviderForMultiply
  521. * @param array $complex1
  522. * @param array $complex2
  523. * @param array $expected
  524. */
  525. public function testMultiply(array $complex1, array $complex2, array $expected)
  526. {
  527. // Given
  528. $c1 = new Complex($complex1['r'], $complex1['i']);
  529. $c2 = new Complex($complex2['r'], $complex2['i']);
  530. // When
  531. $result = $c1->multiply($c2);
  532. // Then
  533. $this->assertEquals($expected['r'], $result->r);
  534. $this->assertEquals($expected['i'], $result->i);
  535. }
  536. public function dataProviderForMultiply(): array
  537. {
  538. return [
  539. [
  540. ['r' => 3, 'i' => 2],
  541. ['r' => 1, 'i' => 4],
  542. ['r' => -5, 'i' => 14],
  543. ],
  544. [
  545. ['r' => 3, 'i' => 13],
  546. ['r' => 7, 'i' => 17],
  547. ['r' => -200, 'i' => 142],
  548. ],
  549. [
  550. ['r' => 6, 'i' => 8],
  551. ['r' => 4, 'i' => -9],
  552. ['r' => 96, 'i' => -22],
  553. ],
  554. [
  555. ['r' => -56, 'i' => 3],
  556. ['r' => -84, 'i' => -4],
  557. ['r' => 4716, 'i' => -28],
  558. ],
  559. ];
  560. }
  561. /**
  562. * @test multiply of real numbers returns the expected complex number
  563. * @dataProvider dataProviderForMultiplyReal
  564. */
  565. public function testMultiplyReal($complex, $real, $expected)
  566. {
  567. // Given
  568. $c = new Complex($complex['r'], $complex['i']);
  569. // When
  570. $result = $c->multiply($real);
  571. // Then
  572. $this->assertEquals($expected['r'], $result->r);
  573. $this->assertEquals($expected['i'], $result->i);
  574. }
  575. public function dataProviderForMultiplyReal()
  576. {
  577. return [
  578. [
  579. ['r' => 3, 'i' => 1],
  580. 2,
  581. ['r' => 6, 'i' => 2],
  582. ],
  583. [
  584. ['r' => 30, 'i' => 13],
  585. 2,
  586. ['r' => 60, 'i' => 26],
  587. ],
  588. ];
  589. }
  590. /**
  591. * @test divide of two complex numbers returns the expected complex number
  592. * @dataProvider dataProviderForDivide
  593. * @param array $complex1
  594. * @param array $complex2
  595. * @param array $expected
  596. */
  597. public function testDivide(array $complex1, array $complex2, array $expected)
  598. {
  599. // Given
  600. $c1 = new Complex($complex1['r'], $complex1['i']);
  601. $c2 = new Complex($complex2['r'], $complex2['i']);
  602. // When
  603. $result = $c1->divide($c2);
  604. // Then
  605. $this->assertEqualsWithDelta($expected['r'], $result->r, 0.00001);
  606. $this->assertEqualsWithDelta($expected['i'], $result->i, 0.00001);
  607. }
  608. public function dataProviderForDivide(): array
  609. {
  610. return [
  611. [
  612. ['r' => 3, 'i' => 2],
  613. ['r' => 4, 'i' => -3],
  614. ['r' => 0.24, 'i' => 0.68],
  615. ],
  616. [
  617. ['r' => 5, 'i' => 5],
  618. ['r' => 6, 'i' => 2],
  619. ['r' => 1, 'i' => 1 / 2],
  620. ],
  621. [
  622. ['r' => 6, 'i' => 2],
  623. ['r' => 7, 'i' => -7],
  624. ['r' => 2 / 7, 'i' => 4 / 7],
  625. ],
  626. [
  627. ['r' => -56, 'i' => 3],
  628. ['r' => -84, 'i' => -4],
  629. ['r' => 69 / 104, 'i' => -7 / 104],
  630. ],
  631. ];
  632. }
  633. /**
  634. * @test divide of real numbers returns the expected complex number
  635. * @dataProvider dataProviderForDivideReal
  636. */
  637. public function testDivideReal($complex, $real, $expected)
  638. {
  639. // Given
  640. $c = new Complex($complex['r'], $complex['i']);
  641. // When
  642. $result = $c->divide($real);
  643. // Then
  644. $this->assertEquals($expected['r'], $result->r);
  645. $this->assertEquals($expected['i'], $result->i);
  646. }
  647. public function dataProviderForDivideReal()
  648. {
  649. return [
  650. [
  651. ['r' => 4, 'i' => 1],
  652. 2,
  653. ['r' => 2, 'i' => 1 / 2],
  654. ],
  655. [
  656. ['r' => 60, 'i' => 9],
  657. 3,
  658. ['r' => 20, 'i' => 3],
  659. ],
  660. ];
  661. }
  662. /**
  663. * @test add throws an Exception\IncorrectTypeException when the argument is not a number or complex number
  664. */
  665. public function testComplexAddException()
  666. {
  667. // Given
  668. $complex = new Complex(1, 1);
  669. // Then
  670. $this->expectException(Exception\IncorrectTypeException::class);
  671. // When
  672. $complex->add("string");
  673. }
  674. /**
  675. * @test subtract throws an Exception\IncorrectTypeException when the argument is not a number or complex number
  676. */
  677. public function testComplexSubtractException()
  678. {
  679. // Given
  680. $complex = new Complex(1, 1);
  681. // Then
  682. $this->expectException(Exception\IncorrectTypeException::class);
  683. // When
  684. $complex->subtract("string");
  685. }
  686. /**
  687. * @test multiply throws an Exception\IncorrectTypeException when the argument is not a number or complex number
  688. */
  689. public function testComplexMultiplyException()
  690. {
  691. // Given
  692. $complex = new Complex(1, 1);
  693. // Then
  694. $this->expectException(Exception\IncorrectTypeException::class);
  695. // When
  696. $complex->multiply("string");
  697. }
  698. /**
  699. * @test divide throws an Exception\IncorrectTypeException when the argument is not a number or complex number
  700. */
  701. public function testComplexDivideException()
  702. {
  703. // Given
  704. $complex = new Complex(1, 1);
  705. // Then
  706. $this->expectException(Exception\IncorrectTypeException::class);
  707. // When
  708. $complex->divide("string");
  709. }
  710. /**
  711. * @test pow of complex numbers raised to a number returns the expected complex number
  712. * @dataProvider dataProviderForPowNumber
  713. * @param array $complex1
  714. * @param number $number
  715. * @param array $expected
  716. */
  717. public function testPowNumber(array $complex1, $number, array $expected)
  718. {
  719. // Given
  720. $c1 = new Complex($complex1['r'], $complex1['i']);
  721. // When
  722. $result = $c1->pow($number);
  723. // Then
  724. $this->assertEqualsWithDelta($expected['r'], $result->r, 0.00001);
  725. $this->assertEqualsWithDelta($expected['i'], $result->i, 0.00001);
  726. }
  727. /**
  728. * https://www.wolframalpha.com/input/?i=%281%2B2*i%29%5E%283%2B4*i%29
  729. */
  730. public function dataProviderForPowNumber(): array
  731. {
  732. return [
  733. [
  734. ['r' => 1, 'i' => 2],
  735. 5,
  736. ['r' => 41, 'i' => -38],
  737. ],
  738. [
  739. ['r' => 7, 'i' => 13],
  740. 0,
  741. ['r' => 1, 'i' => 0],
  742. ],
  743. [
  744. ['r' => 0, 'i' => 0],
  745. 0,
  746. ['r' => 1, 'i' => 0],
  747. ],
  748. ];
  749. }
  750. /**
  751. * @test pow of two complex numbers returns the expected complex number
  752. * @dataProvider dataProviderForPow
  753. * @param array $complex1
  754. * @param array $complex2
  755. * @param array $expected
  756. */
  757. public function testPow(array $complex1, array $complex2, array $expected)
  758. {
  759. // Given
  760. $c1 = new Complex($complex1['r'], $complex1['i']);
  761. $c2 = new Complex($complex2['r'], $complex2['i']);
  762. // When
  763. $result = $c1->pow($c2);
  764. // Then
  765. $this->assertEqualsWithDelta($expected['r'], $result->r, 0.00000001);
  766. $this->assertEqualsWithDelta($expected['i'], $result->i, 0.00000001);
  767. }
  768. /**
  769. * https://www.wolframalpha.com/input/?i=%281%2B2*i%29%5E%283%2B4*i%29
  770. * R: complex(real=1, imaginary=2)**complex(real=3, imaginary=4)
  771. * Python: complex(1,2)**complex(3,4)
  772. */
  773. public function dataProviderForPow(): array
  774. {
  775. return [
  776. [
  777. ['r' => 1, 'i' => 2],
  778. ['r' => 3, 'i' => 4],
  779. ['r' => 0.12900959407446689407705233965244724409184546447229472777070039, 'i' => 0.033924092905170126697617854622547901540547320222677608399651655],
  780. ],
  781. [
  782. ['r' => 1, 'i' => 2],
  783. ['r' => 5, 'i' => 0],
  784. ['r' => 41, 'i' => -38],
  785. ],
  786. [
  787. ['r' => 1, 'i' => 2],
  788. ['r' => 0, 'i' => 0],
  789. ['r' => 1, 'i' => 0],
  790. ],
  791. [
  792. ['r' => 2, 'i' => 2],
  793. ['r' => -2, 'i' => -2],
  794. ['r' => -0.5251869237872764, 'i' => 0.2928344540350973],
  795. ],
  796. [
  797. ['r' => -2, 'i' => -2],
  798. ['r' => -2, 'i' => -2],
  799. ['r' => -9.807565e-04, 'i' => 5.468516e-04],
  800. ],
  801. [
  802. ['r' => 83, 'i' => 24],
  803. ['r' => 4, 'i' => 6],
  804. ['r' => -9503538.518957876, 'i' => 3956277.4270916637],
  805. ],
  806. [
  807. ['r' => 2, 'i' => 3],
  808. ['r' => 4, 'i' => 5],
  809. ['r' => -0.7530458367485596, 'i' => -0.9864287886477445],
  810. ],
  811. [
  812. ['r' => -2, 'i' => 3],
  813. ['r' => 4, 'i' => 5],
  814. ['r' => -0.0027390773950467934, 'i' => 0.0021275418620241996],
  815. ],
  816. [
  817. ['r' => 2, 'i' => -3],
  818. ['r' => 4, 'i' => 5],
  819. ['r' => -18175.48769862527, 'i' => 14117.567839250678],
  820. ],
  821. [
  822. ['r' => 2, 'i' => 3],
  823. ['r' => -4, 'i' => 5],
  824. ['r' => -3.4315770545555685e-05, 'i' => 2.6654317433786663e-05],
  825. ],
  826. [
  827. ['r' => 2, 'i' => 3],
  828. ['r' => 4, 'i' => -5],
  829. ['r' => -18175.48769862527, 'i' => -14117.567839250678],
  830. ],
  831. [
  832. ['r' => 0, 'i' => 0],
  833. ['r' => 0, 'i' => 0],
  834. ['r' => 1, 'i' => 0],
  835. ],
  836. ];
  837. }
  838. /**
  839. * @test pow IncorrectTypeException
  840. */
  841. public function testComplexPowTypeError()
  842. {
  843. // Given
  844. $c = new Complex(1, 2);
  845. // And
  846. $nonNumber = 'KaPoW!';
  847. // Then
  848. $this->expectException(Exception\IncorrectTypeException::class);
  849. // When
  850. $c->pow($nonNumber);
  851. }
  852. /**
  853. * @test inverse returns the expected complex number
  854. * @dataProvider dataProviderForInverse
  855. * @param number $r
  856. * @param number $i
  857. * @param number $expected_r
  858. * @param number $expected_i
  859. */
  860. public function testInverse($r, $i, $expected_r, $expected_i)
  861. {
  862. // Given
  863. $c = new Complex($r, $i);
  864. // When
  865. $inverse = $c->inverse();
  866. // Then
  867. $this->assertEqualsWithDelta($expected_r, $inverse->r, 0.00001);
  868. $this->assertEqualsWithDelta($expected_i, $inverse->i, 0.00001);
  869. }
  870. public function dataProviderForInverse(): array
  871. {
  872. return [
  873. [1, 0, 1, 0],
  874. [0, 1, 0, -1],
  875. [1, 1, 1 / 2, -1 / 2],
  876. [4, 6, 1 / 13, -3 / 26],
  877. [-4, 6, -1 / 13, -3 / 26],
  878. [4, -6, 1 / 13, 3 / 26],
  879. [-4, -6, -1 / 13, 3 / 26],
  880. ];
  881. }
  882. /**
  883. * @test inverse throws an Exception\BadDataException when value is 0 + 0i
  884. */
  885. public function testInverseException()
  886. {
  887. // Given
  888. $complex = new Complex(0, 0);
  889. // Then
  890. $this->expectException(Exception\BadDataException::class);
  891. // When
  892. $complex->inverse();
  893. }
  894. /**
  895. * @test equals returns true if the complex numbers are the same
  896. * @dataProvider dataProviderForComplexNumbers
  897. * @param number $r
  898. * @param number $i
  899. */
  900. public function testEqualsTrue($r, $i)
  901. {
  902. // Given
  903. $c1 = new Complex($r, $i);
  904. $c2 = new Complex($r, $i);
  905. // When
  906. $isEqual = $c1->Equals($c2);
  907. // Then
  908. $this->assertTrue($isEqual);
  909. }
  910. /**
  911. * @test equals returns false if the complex numbers are different
  912. * @dataProvider dataProviderForComplexNumbers
  913. * @param number $r
  914. * @param number $i
  915. */
  916. public function testEqualsFalse($r, $i)
  917. {
  918. // Given
  919. $c1 = new Complex($r, $i);
  920. $c2 = new Complex($r + 1, $i - 1);
  921. // When
  922. $isNotEqual = $c1->Equals($c2);
  923. // Then
  924. $this->assertFalse($isNotEqual);
  925. }
  926. public function dataProviderForComplexNumbers(): array
  927. {
  928. return [
  929. [0, 0],
  930. [1, 0],
  931. [0, 1],
  932. [1, 1],
  933. [1, 2],
  934. [2, 1],
  935. [2, 2],
  936. [3, 4],
  937. [5, 3],
  938. [-1, 0],
  939. [0, 1],
  940. [-1, 1],
  941. [-1, 2],
  942. [-2, 1],
  943. [-2, 2],
  944. [-3, 4],
  945. [-5, 3],
  946. [1, 0],
  947. [0, -1],
  948. [1, -1],
  949. [1, -2],
  950. [2, -1],
  951. [2, -2],
  952. [3, -4],
  953. [5, -3],
  954. [-1, 0],
  955. [0, -1],
  956. [-1, -1],
  957. [-1, -2],
  958. [-2, -1],
  959. [-2, -2],
  960. [-3, -4],
  961. [-5, -3],
  962. ];
  963. }
  964. }