ArithmeticTest.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. <?php
  2. namespace MathPHP\Tests\Arithmetic;
  3. use MathPHP\Arithmetic;
  4. use MathPHP\Exception;
  5. class ArithmeticTest extends \PHPUnit\Framework\TestCase
  6. {
  7. /**
  8. * @test copySign
  9. * @dataProvider dataProviderForCopySign
  10. * @param float $x
  11. * @param float $y
  12. * @param float $x_with_y_sign
  13. */
  14. public function testCopySign(float $x, float $y, float $x_with_y_sign)
  15. {
  16. // When
  17. $copy_sign = Arithmetic::copySign($x, $y);
  18. // Then
  19. $this->assertSame($x_with_y_sign, $copy_sign);
  20. }
  21. /**
  22. * @return array [x, y, x with y sign]
  23. */
  24. public function dataProviderForCopySign(): array
  25. {
  26. return [
  27. [1, 1, 1],
  28. [1, -1, -1],
  29. [-1, 1, 1],
  30. [-1, -1, -1],
  31. [2, 1, 2],
  32. [2, -1, -2],
  33. [-2, 1, 2],
  34. [-2, -1, -2],
  35. [3, 0, 3],
  36. [3, -0, 3],
  37. [-3, 0, 3],
  38. [-3, -0, 3],
  39. [2.3, 1, 2.3],
  40. [2.3, -1, -2.3],
  41. [-2.3, 1, 2.3],
  42. [-2.3, -1, -2.3],
  43. [INF, 1, INF],
  44. [INF, -1, -INF],
  45. [-INF, 1, INF],
  46. [-INF, -1, -INF],
  47. ];
  48. }
  49. /**
  50. * @test root returns the expected value.
  51. * @dataProvider dataProviderForRoot
  52. * @param float $x
  53. * @param int $n
  54. * @param float $expected_root
  55. */
  56. public function testRoot(float $x, int $n, float $expected_root)
  57. {
  58. // When
  59. $root = Arithmetic::root($x, $n);
  60. // Then
  61. $this->assertEqualsWithDelta($expected_root, $root, 0.000000001);
  62. }
  63. /**
  64. * @return array
  65. */
  66. public function dataProviderForRoot(): array
  67. {
  68. return [
  69. [1, 6, 1],
  70. [-1, 5, -1],
  71. [3125, 5, 5],
  72. [0, 3, 0],
  73. [4, 2, 2],
  74. [9, 2, 3],
  75. [16, 2, 4],
  76. [1, 3, 1],
  77. [-1, 3, -1],
  78. [2, 3, 1.259921049894873],
  79. [-2, 3, -1.259921049894873],
  80. [3, 3, 1.442249570307408],
  81. [-3, 3, -1.442249570307408],
  82. [8, 3, 2],
  83. [-8, 3, -2],
  84. [27, 3, 3],
  85. [-27, 3, -3],
  86. [64, 3, 4],
  87. [-64, 3, -4],
  88. [125, 3, 5],
  89. [-125, 3, -5],
  90. [245.362, 3, 6.260405067916984],
  91. [-245.362, 3, -6.260405067916984],
  92. [0.0548, 3, 0.379833722265818],
  93. [-0.0548, 3, -0.379833722265818],
  94. [81, 4, 3],
  95. [100, 4, 3.1622776602],
  96. ];
  97. }
  98. /**
  99. * @test cubeRoot returns the expected value.
  100. * @dataProvider dataProviderForCubeRoot
  101. * @param float $x
  102. * @param float $expected_cube_root
  103. */
  104. public function testCubeRoot(float $x, float $expected_cube_root)
  105. {
  106. // When
  107. $cube_root = Arithmetic::cubeRoot($x);
  108. // Then
  109. $this->assertEqualsWithDelta($expected_cube_root, $cube_root, 0.000000001);
  110. }
  111. /**
  112. * @return array
  113. */
  114. public function dataProviderForCubeRoot(): array
  115. {
  116. return [
  117. [0, 0],
  118. [1, 1],
  119. [-1, -1],
  120. [2, 1.259921049894873],
  121. [-2, -1.259921049894873],
  122. [3, 1.442249570307408],
  123. [-3, -1.442249570307408],
  124. [8, 2],
  125. [-8, -2],
  126. [27, 3],
  127. [-27, -3],
  128. [64, 4],
  129. [-64, -4],
  130. [125, 5],
  131. [-125, -5],
  132. [245.362, 6.260405067916984],
  133. [-245.362, -6.260405067916984],
  134. [0.0548, 0.379833722265818],
  135. [-0.0548, -0.379833722265818],
  136. ];
  137. }
  138. /**
  139. * @test digitSum returns the expected sum of digits for base 10
  140. * @dataProvider dataProviderForDigitSumBaseTen
  141. * @param int $x
  142. * @param int $expected
  143. */
  144. public function testDigitSum(int $x, int $expected)
  145. {
  146. // Given
  147. $base = 10;
  148. // When
  149. $digital_sum = Arithmetic::digitSum($x, $base);
  150. // Then
  151. $this->assertEquals($expected, $digital_sum);
  152. }
  153. /**
  154. * @return array
  155. */
  156. public function dataProviderForDigitSumBaseTen(): array
  157. {
  158. return [
  159. [0, 0],
  160. [1, 1],
  161. [2, 2],
  162. [3, 3],
  163. [4, 4],
  164. [5, 5],
  165. [6, 6],
  166. [7, 7],
  167. [8, 8],
  168. [9, 9],
  169. [10, 1],
  170. [11, 2],
  171. [12, 3],
  172. [13, 4],
  173. [14, 5],
  174. [15, 6],
  175. [16, 7],
  176. [17, 8],
  177. [18, 9],
  178. [19, 10],
  179. [20, 2],
  180. [21, 3],
  181. [22, 4],
  182. [23, 5],
  183. [24, 6],
  184. [25, 7],
  185. [26, 8],
  186. [27, 9],
  187. [28, 10],
  188. [29, 11],
  189. [30, 3],
  190. [31, 4],
  191. [32, 5],
  192. [33, 6],
  193. [34, 7],
  194. [111, 3],
  195. [222, 6],
  196. [123, 6],
  197. [999, 27],
  198. [152, 8],
  199. [84001, 13],
  200. [18, 9],
  201. [27, 9],
  202. [36, 9],
  203. [45, 9],
  204. [54, 9],
  205. [63, 9],
  206. [72, 9],
  207. [81, 9],
  208. [90, 9],
  209. [99, 18],
  210. ];
  211. }
  212. /**
  213. * @test digitSum returns the expected sum of digits for base 2
  214. * @dataProvider dataProviderForDigitSumBaseTwo
  215. * @param int $x
  216. * @param int $expected
  217. */
  218. public function testDigitSumBaseTwo(int $x, int $expected)
  219. {
  220. // Given
  221. $base = 2;
  222. // When
  223. $digital_sum = Arithmetic::digitSum($x, $base);
  224. // Then
  225. $this->assertEquals($expected, $digital_sum);
  226. }
  227. /**
  228. * @return array
  229. */
  230. public function dataProviderForDigitSumBaseTwo(): array
  231. {
  232. return [
  233. [0b0, 0],
  234. [0b1, 1],
  235. [0b10, 1],
  236. [0b11, 2],
  237. [0b100, 1],
  238. [0b101, 2],
  239. [0b110, 2],
  240. [0b111, 3],
  241. [0b1000, 1],
  242. [0b1001, 2],
  243. [0b1010, 2],
  244. [0b1011, 3],
  245. [0b1100, 2],
  246. [0b1101, 3],
  247. [0b111, 3],
  248. ];
  249. }
  250. /**
  251. * @test digitalRoot returns the expected root
  252. * @dataProvider dataProviderForDigitalRoot
  253. * @param int $x
  254. * @param int $expected_root
  255. */
  256. public function testDigitalRoot(int $x, int $expected_root)
  257. {
  258. // When
  259. $digital_root = Arithmetic::digitalRoot($x);
  260. // Then
  261. $this->assertEquals($expected_root, $digital_root);
  262. }
  263. /**
  264. * @return array
  265. */
  266. public function dataProviderForDigitalRoot(): array
  267. {
  268. return [
  269. [0, 0],
  270. [1, 1],
  271. [2, 2],
  272. [3, 3],
  273. [4, 4],
  274. [5, 5],
  275. [6, 6],
  276. [7, 7],
  277. [8, 8],
  278. [9, 9],
  279. [10, 1],
  280. [11, 2],
  281. [12, 3],
  282. [13, 4],
  283. [14, 5],
  284. [15, 6],
  285. [16, 7],
  286. [17, 8],
  287. [18, 9],
  288. [19, 1],
  289. [20, 2],
  290. [21, 3],
  291. [22, 4],
  292. [23, 5],
  293. [24, 6],
  294. [25, 7],
  295. [26, 8],
  296. [27, 9],
  297. [28, 1],
  298. [29, 2],
  299. [30, 3],
  300. [31, 4],
  301. [32, 5],
  302. [33, 6],
  303. [34, 7],
  304. [111, 3],
  305. [222, 6],
  306. [123, 6],
  307. [999, 9],
  308. [152, 8],
  309. [84001, 4],
  310. [65536, 7],
  311. [18, 9],
  312. [27, 9],
  313. [36, 9],
  314. [45, 9],
  315. [54, 9],
  316. [63, 9],
  317. [72, 9],
  318. [81, 9],
  319. [90, 9],
  320. [99, 9],
  321. [108, 9],
  322. ];
  323. }
  324. /**
  325. * @test almostEqual
  326. * @dataProvider dataProviderForAlmostEqual
  327. * @param float $x
  328. * @param float $y
  329. * @param float $ε
  330. * @param bool $expected
  331. */
  332. public function testAlmostEqual(float $x, float $y, float $ε, bool $expected)
  333. {
  334. // When
  335. $equal = Arithmetic::almostEqual($x, $y, $ε);
  336. // Then
  337. $this->assertSame($expected, $equal);
  338. }
  339. /**
  340. * @return array [x, y, ε, expected] .00000000000035
  341. */
  342. public function dataProviderForAlmostEqual(): array
  343. {
  344. return [
  345. [0, 0, 0, true],
  346. [0, 0, 0.0, true],
  347. [0, 0, 0.0000000001, true],
  348. [0, 1, 0.0000000001, false],
  349. [-0, -0, 0, true],
  350. [-0, -0, 0.0, true],
  351. [-0, -0, 0.0000000001, true],
  352. [-0, -1, 0.0000000001, false],
  353. [1.2345678, 1.23456789, 0.1, true],
  354. [1.2345678, 1.23456789, 0.01, true],
  355. [1.2345678, 1.23456789, 0.001, true],
  356. [1.2345678, 1.23456789, 0.0001, true],
  357. [1.2345678, 1.23456789, 0.00001, true],
  358. [1.2345678, 1.23456789, 0.000001, true],
  359. [1.2345678, 1.23456789, 0.0000001, true],
  360. [1.2345678, 1.23456789, 0.00000001, false],
  361. [1.2345678, 1.23456789, 0.0000000001, false],
  362. [1.2345678, 1.23456789, 0.00000000001, false],
  363. [-1.2345678, -1.23456789, 0.1, true],
  364. [-1.2345678, -1.23456789, 0.01, true],
  365. [-1.2345678, -1.23456789, 0.001, true],
  366. [-1.2345678, -1.23456789, 0.0001, true],
  367. [-1.2345678, -1.23456789, 0.00001, true],
  368. [-1.2345678, -1.23456789, 0.000001, true],
  369. [-1.2345678, -1.23456789, 0.0000001, true],
  370. [-1.2345678, -1.23456789, 0.00000001, false],
  371. [-1.2345678, -1.23456789, 0.0000000001, false],
  372. [-1.2345678, -1.23456789, 0.00000000001, false],
  373. [0.00000003458, 0.0000000345599999, 0.00000001, true],
  374. [0.00000003458, 0.0000000345599999, 0.000000001, true],
  375. [0.00000003458, 0.0000000345599999, 0.0000000001, true],
  376. [0.00000003458, 0.0000000345599999, 0.00000000001, false],
  377. [0.00000003458, 0.0000000345599999, 0.000000000001, false],
  378. [0.00000003458, 0.0000000345599999, 0.0000000000001, false],
  379. [0.00000003458, 0.0000000345764999, 0.00000001, true],
  380. [0.00000003458, 0.0000000345764999, 0.000000001, true],
  381. [0.00000003458, 0.0000000345764999, 0.0000000001, true],
  382. [0.00000003458, 0.0000000345764999, 0.00000000001, true],
  383. [0.00000003458, 0.0000000345764999, 0.000000000001, false],
  384. [0.00000003458, 0.0000000345764999, 0.0000000000001, false],
  385. [-0.00000003458, -0.0000000345599999, 0.00000001, true],
  386. [-0.00000003458, -0.0000000345599999, 0.000000001, true],
  387. [-0.00000003458, -0.0000000345599999, 0.0000000001, true],
  388. [-0.00000003458, -0.0000000345599999, 0.00000000001, false],
  389. [-0.00000003458, -0.0000000345599999, 0.000000000001, false],
  390. [-0.00000003458, -0.0000000345599999, 0.0000000000001, false],
  391. [-0.00000003458, -0.0000000345764999, 0.00000001, true],
  392. [-0.00000003458, -0.0000000345764999, 0.000000001, true],
  393. [-0.00000003458, -0.0000000345764999, 0.0000000001, true],
  394. [-0.00000003458, -0.0000000345764999, 0.00000000001, true],
  395. [-0.00000003458, -0.0000000345764999, 0.000000000001, false],
  396. [-0.00000003458, -0.0000000345764999, 0.0000000000001, false],
  397. [0.00000003458, 0.00000003455, 0.00000001, true],
  398. [0.00000003458, 0.00000003455, 0.000000001, true],
  399. [0.00000003458, 0.00000003455, 0.0000000001, true],
  400. [0.00000003458, 0.00000003455, 0.00000000001, false],
  401. [0.00000003458, 0.00000003455, 0.000000000001, false],
  402. [0.00000003458, 0.00000003455, 0.0000000000001, false],
  403. [-0.00000003458, -0.00000003455, 0.00000001, true],
  404. [-0.00000003458, -0.00000003455, 0.000000001, true],
  405. [-0.00000003458, -0.00000003455, 0.0000000001, true],
  406. [-0.00000003458, -0.00000003455, 0.00000000001, false],
  407. [-0.00000003458, -0.00000003455, 0.000000000001, false],
  408. [-0.00000003458, -0.00000003455, 0.0000000000001, false],
  409. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000001, true],
  410. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000001, true],
  411. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.0000000001, true],
  412. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000000001, true],
  413. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000000001, true],
  414. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.0000000000001, true],
  415. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000000000001, true],
  416. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000000000001, true],
  417. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.0000000000000001, true],
  418. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000000000000001, true],
  419. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000000000000001, true],
  420. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.0000000000000000001, true],
  421. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000000000000000001, true],
  422. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000000000000000001, true],
  423. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.0000000000000000000001, true],
  424. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000000000000000000001, true],
  425. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000000000000000000001, false],
  426. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.0000000000000000000000001, false],
  427. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.00000000000000000000000001, false],
  428. [0.0000000000000000044746732, 0.0000000000000000044746639325, 0.000000000000000000000000001, false],
  429. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000001, true],
  430. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000001, true],
  431. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.0000000001, true],
  432. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000000001, true],
  433. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000000001, true],
  434. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.0000000000001, true],
  435. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000000000001, true],
  436. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000000000001, true],
  437. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.0000000000000001, true],
  438. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000000000000001, true],
  439. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000000000000001, true],
  440. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.0000000000000000001, true],
  441. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000000000000000001, true],
  442. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000000000000000001, true],
  443. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.0000000000000000000001, true],
  444. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000000000000000000001, true],
  445. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000000000000000000001, false],
  446. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.0000000000000000000000001, false],
  447. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.00000000000000000000000001, false],
  448. [-0.0000000000000000044746732, -0.0000000000000000044746639325, 0.000000000000000000000000001, false],
  449. ];
  450. }
  451. /**
  452. * @test modulo of positive dividend and divisor
  453. * @dataProvider dataProviderForModuloPositiveDividendAndDivisor
  454. * @param int $a dividend
  455. * @param int $n divisor
  456. * @param int $expected
  457. */
  458. public function testModuloPositiveDividendAndDivisor(int $a, int $n, int $expected)
  459. {
  460. // When
  461. $modulo = Arithmetic::modulo($a, $n);
  462. // Then
  463. $this->assertEquals($expected, $modulo);
  464. }
  465. /**
  466. * Test data generated with R: a %% n
  467. * @return array (dividend, divisor, expected)
  468. */
  469. public function dataProviderForModuloPositiveDividendAndDivisor(): array
  470. {
  471. return [
  472. [0, 1, 0],
  473. [0, 2, 0],
  474. [1, 1, 0],
  475. [1, 2, 1],
  476. [2, 1, 0],
  477. [2, 2, 0],
  478. [2, 3, 2],
  479. [3, 2, 1],
  480. [5, 3, 2],
  481. [10, 1, 0],
  482. [10, 2, 0],
  483. [10, 3, 1],
  484. [10, 4, 2],
  485. [10, 5, 0],
  486. [10, 6, 4],
  487. [10, 7, 3],
  488. [10, 8, 2],
  489. [10, 9, 1],
  490. [10, 10, 0],
  491. [12, 5, 2],
  492. [18, 3, 0],
  493. [100, 3, 1],
  494. [100, 7, 2],
  495. [340, 60, 40],
  496. ];
  497. }
  498. /**
  499. * @test Modulo is the same as the built-in remainder (%) operator when the dividend and divisor are positive
  500. */
  501. public function testModuloPositiveDividendAndDivisorIsSameAsBuiltInRemainderOperator()
  502. {
  503. // Given
  504. foreach (\range(0, 20) as $a) {
  505. foreach (\range(1, 20) as $n) {
  506. // When
  507. $remainder = $a % $n;
  508. $modulo = Arithmetic::modulo($a, $n);
  509. // Then
  510. $this->assertEquals($remainder, $modulo);
  511. }
  512. }
  513. }
  514. /**
  515. * @test modulo of negative dividend
  516. * @dataProvider dataProviderForModuloNegativeDividend
  517. * @param int $a dividend
  518. * @param int $n divisor
  519. * @param int $expected
  520. */
  521. public function testModuloNegativeDividend(int $a, int $n, int $expected)
  522. {
  523. // When
  524. $modulo = Arithmetic::modulo($a, $n);
  525. // Then
  526. $this->assertEquals($expected, $modulo);
  527. }
  528. /**
  529. * Test data generated with R: a %% n
  530. * @return array (dividend, divisor, expected)
  531. */
  532. public function dataProviderForModuloNegativeDividend(): array
  533. {
  534. return [
  535. [-0, 1, 0],
  536. [-0, 2, 0],
  537. [-1, 1, 0],
  538. [-1, 2, 1],
  539. [-2, 1, 0],
  540. [-2, 2, 0],
  541. [-2, 3, 1],
  542. [-3, 2, 1],
  543. [-5, 3, 1],
  544. [-10, 1, 0],
  545. [-10, 2, 0],
  546. [-10, 3, 2],
  547. [-10, 4, 2],
  548. [-10, 5, 0],
  549. [-10, 6, 2],
  550. [-10, 7, 4],
  551. [-10, 8, 6],
  552. [-10, 9, 8],
  553. [-10, 10, 0],
  554. [-12, 5, 3],
  555. [-18, 3, 0],
  556. [-100, 3, 2],
  557. [-100, 7, 5],
  558. [-340, 60, 20],
  559. ];
  560. }
  561. /**
  562. * @test modulo of negative divisor
  563. * @dataProvider dataProviderForModuloNegativeDivisor
  564. * @param int $a dividend
  565. * @param int $n divisor
  566. * @param int $expected
  567. */
  568. public function testModuloNegativeDivisor(int $a, int $n, int $expected)
  569. {
  570. // When
  571. $modulo = Arithmetic::modulo($a, $n);
  572. // Then
  573. $this->assertEquals($expected, $modulo);
  574. }
  575. /**
  576. * Test data generated with R: a %% n
  577. * @return array (dividend, divisor, expected)
  578. */
  579. public function dataProviderForModuloNegativeDivisor(): array
  580. {
  581. return [
  582. [0, -1, 0],
  583. [0, -2, 0],
  584. [1, -1, 0],
  585. [1, -2, -1],
  586. [2, -1, 0],
  587. [2, -2, 0],
  588. [2, -3, -1],
  589. [3, -2, -1],
  590. [5, -3, -1],
  591. [10, -1, 0],
  592. [10, -2, 0],
  593. [10, -3,- 2],
  594. [10, -4,- 2],
  595. [10, -5, 0],
  596. [10, -6, -2],
  597. [10, -7, -4],
  598. [10, -8, -6],
  599. [10, -9, -8],
  600. [10, -10, 0],
  601. [12, -5, -3],
  602. [18, -3, 0],
  603. [100, -3, -2],
  604. [100, -7, -5],
  605. [340, -60, -20],
  606. ];
  607. }
  608. /**
  609. * @test modulo of negative dividend and divisor
  610. * @dataProvider dataProviderForModuloNegativeDividendAndDivisor
  611. * @param int $a dividend
  612. * @param int $n divisor
  613. * @param int $expected
  614. */
  615. public function testModuloNegativeDividendAndDivisor(int $a, int $n, int $expected)
  616. {
  617. // When
  618. $modulo = Arithmetic::modulo($a, $n);
  619. // Then
  620. $this->assertEquals($expected, $modulo);
  621. }
  622. /**
  623. * Test data generated with R: a %% n
  624. * @return array (dividend, divisor, expected)
  625. */
  626. public function dataProviderForModuloNegativeDividendAndDivisor(): array
  627. {
  628. return [
  629. [-0, -1, 0],
  630. [-0, -2, 0],
  631. [-1, -1, 0],
  632. [-1, -2, -1],
  633. [-2, -1, 0],
  634. [-2, -2, 0],
  635. [-2, -3, -2],
  636. [-3, -2, -1],
  637. [-5, -3, -2],
  638. [-10, -1, 0],
  639. [-10, -2, 0],
  640. [-10, -3, -1],
  641. [-10, -4, -2],
  642. [-10, -5, 0],
  643. [-10, -6, -4],
  644. [-10, -7, -3],
  645. [-10, -8, -2],
  646. [-10, -9, -1],
  647. [-10, -10, 0],
  648. [-12, -5, -2],
  649. [-18, -3, 0],
  650. [-100, -3, -1],
  651. [-100, -7, -2],
  652. [-340, -60, -40],
  653. ];
  654. }
  655. /**
  656. * @test modulo of of zero divisor is just the dividend
  657. * @dataProvider dataProviderForModuloZeroDivisor
  658. * @param int $a dividend
  659. * @param int $n divisor
  660. */
  661. public function testModuloZeroDivisorIsDividend(int $a, int $n)
  662. {
  663. // When
  664. $modulo = Arithmetic::modulo($a, $n);
  665. // Then
  666. $this->assertEquals($a, $modulo);
  667. }
  668. /**
  669. * @return array (dividend, divisor, expected)
  670. */
  671. public function dataProviderForModuloZeroDivisor(): array
  672. {
  673. return [
  674. [-5, 0],
  675. [-4, 0],
  676. [-3, 0],
  677. [-2, 0],
  678. [-1, 0],
  679. [0, 0],
  680. [1, 0],
  681. [2, 0],
  682. [3, 0],
  683. [4, 0],
  684. [5, 0],
  685. ];
  686. }
  687. /**
  688. * @test isqrt
  689. * @dataProvider dataProviderForIsqrt
  690. * @param float $x
  691. * @param int $expected
  692. */
  693. public function testIsqrt(float $x, int $expected)
  694. {
  695. // When
  696. $isqrt = Arithmetic::isqrt($x);
  697. // Then
  698. $this->assertEquals($expected, $isqrt);
  699. }
  700. public function dataProviderForIsqrt(): array
  701. {
  702. return [
  703. [0, 0],
  704. [0.5, 0],
  705. [1, 1],
  706. [2, 1],
  707. [3, 1],
  708. [3.99, 1],
  709. [4, 2],
  710. [5, 2],
  711. [8, 2],
  712. [8.9939, 2],
  713. [9, 3],
  714. [25, 5],
  715. [27, 5],
  716. ];
  717. }
  718. /**
  719. * @test isqrt error when value is negative
  720. */
  721. public function testIsqrtNegativeNumberIsBadParameterError()
  722. {
  723. // Given
  724. $x = -1;
  725. // Then
  726. $this->expectException(Exception\BadParameterException::class);
  727. // When
  728. Arithmetic::isqrt($x);
  729. }
  730. }