Coverage for algebra/tests/test_common.py: 100%

233 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1"""Define the unit tests for the :mod:`colour.algebra.common` module.""" 

2 

3from __future__ import annotations 

4 

5from itertools import product 

6 

7import numpy as np 

8import pytest 

9 

10from colour.algebra import ( 

11 eigen_decomposition, 

12 euclidean_distance, 

13 get_sdiv_mode, 

14 is_identity, 

15 is_spow_enabled, 

16 linear_conversion, 

17 linstep_function, 

18 manhattan_distance, 

19 normalise_maximum, 

20 normalise_vector, 

21 sdiv, 

22 sdiv_mode, 

23 set_sdiv_mode, 

24 set_spow_enable, 

25 smoothstep_function, 

26 spow, 

27 spow_enable, 

28 vecmul, 

29) 

30from colour.constants import TOLERANCE_ABSOLUTE_TESTS 

31from colour.utilities import ColourRuntimeWarning, ignore_numpy_errors 

32 

33__author__ = "Colour Developers" 

34__copyright__ = "Copyright 2013 Colour Developers" 

35__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause" 

36__maintainer__ = "Colour Developers" 

37__email__ = "colour-developers@colour-science.org" 

38__status__ = "Production" 

39 

40__all__ = [ 

41 "TestGetSdivMode", 

42 "TestSetSdivMode", 

43 "TestSdivMode", 

44 "TestSdiv", 

45 "TestIsSpowEnabled", 

46 "TestSetSpowEnabled", 

47 "TestSpowEnable", 

48 "TestSpow", 

49 "TestSmoothstepFunction", 

50 "TestNormaliseVector", 

51 "TestNormaliseMaximum", 

52 "TestVectorDot", 

53 "TestEuclideanDistance", 

54 "TestManhattanDistance", 

55 "TestLinearConversion", 

56 "TestLinstepFunction", 

57 "TestIsIdentity", 

58 "TestEigenDecomposition", 

59] 

60 

61 

62class TestGetSdivMode: 

63 """ 

64 Define :func:`colour.algebra.common.get_sdiv_mode` definition unit tests 

65 methods. 

66 """ 

67 

68 def test_get_sdiv_mode(self) -> None: 

69 """Test :func:`colour.algebra.common.get_sdiv_mode` definition.""" 

70 

71 with sdiv_mode("Numpy"): 

72 assert get_sdiv_mode() == "numpy" 

73 

74 with sdiv_mode("Ignore"): 

75 assert get_sdiv_mode() == "ignore" 

76 

77 with sdiv_mode("Warning"): 

78 assert get_sdiv_mode() == "warning" 

79 

80 with sdiv_mode("Raise"): 

81 assert get_sdiv_mode() == "raise" 

82 

83 with sdiv_mode("Ignore Zero Conversion"): 

84 assert get_sdiv_mode() == "ignore zero conversion" 

85 

86 with sdiv_mode("Warning Zero Conversion"): 

87 assert get_sdiv_mode() == "warning zero conversion" 

88 

89 with sdiv_mode("Ignore Limit Conversion"): 

90 assert get_sdiv_mode() == "ignore limit conversion" 

91 

92 with sdiv_mode("Warning Limit Conversion"): 

93 assert get_sdiv_mode() == "warning limit conversion" 

94 

95 

96class TestSetSdivMode: 

97 """ 

98 Define :func:`colour.algebra.common.set_sdiv_mode` definition unit tests 

99 methods. 

100 """ 

101 

102 def test_set_sdiv_mode(self) -> None: 

103 """Test :func:`colour.algebra.common.set_sdiv_mode` definition.""" 

104 

105 with sdiv_mode(get_sdiv_mode()): 

106 set_sdiv_mode("Numpy") 

107 assert get_sdiv_mode() == "numpy" 

108 

109 set_sdiv_mode("Ignore") 

110 assert get_sdiv_mode() == "ignore" 

111 

112 set_sdiv_mode("Warning") 

113 assert get_sdiv_mode() == "warning" 

114 

115 set_sdiv_mode("Raise") 

116 assert get_sdiv_mode() == "raise" 

117 

118 set_sdiv_mode("Ignore Zero Conversion") 

119 assert get_sdiv_mode() == "ignore zero conversion" 

120 

121 set_sdiv_mode("Warning Zero Conversion") 

122 assert get_sdiv_mode() == "warning zero conversion" 

123 

124 set_sdiv_mode("Ignore Limit Conversion") 

125 assert get_sdiv_mode() == "ignore limit conversion" 

126 

127 set_sdiv_mode("Warning Limit Conversion") 

128 assert get_sdiv_mode() == "warning limit conversion" 

129 

130 

131class TestSdivMode: 

132 """ 

133 Define :func:`colour.algebra.common.sdiv_mode` definition unit 

134 tests methods. 

135 """ 

136 

137 def test_sdiv_mode(self) -> None: 

138 """Test :func:`colour.algebra.common.sdiv_mode` definition.""" 

139 

140 with sdiv_mode("Raise"): 

141 assert get_sdiv_mode() == "raise" 

142 

143 with sdiv_mode("Ignore Zero Conversion"): 

144 assert get_sdiv_mode() == "ignore zero conversion" 

145 

146 @sdiv_mode("Raise") 

147 def fn_a() -> None: 

148 """:func:`sdiv_mode` unit tests :func:`fn_a` definition.""" 

149 

150 assert get_sdiv_mode() == "raise" 

151 

152 fn_a() 

153 

154 @sdiv_mode("Ignore Zero Conversion") 

155 def fn_b() -> None: 

156 """:func:`sdiv_mode` unit tests :func:`fn_b` definition.""" 

157 

158 assert get_sdiv_mode() == "ignore zero conversion" 

159 

160 fn_b() 

161 

162 

163class TestSdiv: 

164 """ 

165 Define :func:`colour.algebra.common.sdiv` definition unit 

166 tests methods. 

167 """ 

168 

169 def test_sdiv(self) -> None: 

170 """Test :func:`colour.algebra.common.sdiv` definition.""" 

171 

172 a = np.array([0, 1, 2]) 

173 b = np.array([2, 1, 0]) 

174 

175 with sdiv_mode("Numpy"): 

176 pytest.warns(RuntimeWarning, sdiv, a, b) 

177 

178 with sdiv_mode("Ignore"): 

179 np.testing.assert_equal(sdiv(a, b), np.array([0, 1, np.inf])) 

180 

181 with sdiv_mode("Warning"): 

182 pytest.warns(RuntimeWarning, sdiv, a, b) 

183 np.testing.assert_equal(sdiv(a, b), np.array([0, 1, np.inf])) 

184 

185 with sdiv_mode("Raise"): 

186 pytest.raises(FloatingPointError, sdiv, a, b) 

187 

188 with sdiv_mode("Ignore Zero Conversion"): 

189 np.testing.assert_equal(sdiv(a, b), np.array([0, 1, 0])) 

190 

191 with sdiv_mode("Warning Zero Conversion"): 

192 pytest.warns(RuntimeWarning, sdiv, a, b) 

193 np.testing.assert_equal(sdiv(a, b), np.array([0, 1, 0])) 

194 

195 with sdiv_mode("Ignore Limit Conversion"): 

196 np.testing.assert_equal(sdiv(a, b), np.nan_to_num(np.array([0, 1, np.inf]))) 

197 

198 with sdiv_mode("Warning Limit Conversion"): 

199 pytest.warns(RuntimeWarning, sdiv, a, b) 

200 np.testing.assert_equal(sdiv(a, b), np.nan_to_num(np.array([0, 1, np.inf]))) 

201 

202 with sdiv_mode("Replace With Epsilon"): 

203 np.testing.assert_allclose( 

204 sdiv(a, b), np.array([0, 1, 2 / np.finfo(np.double).eps]) 

205 ) 

206 

207 with sdiv_mode("Warning Replace With Epsilon"): 

208 pytest.warns(ColourRuntimeWarning, sdiv, a, b) 

209 np.testing.assert_allclose( 

210 sdiv(a, b), np.array([0, 1, 2 / np.finfo(np.double).eps]) 

211 ) 

212 

213 

214class TestIsSpowEnabled: 

215 """ 

216 Define :func:`colour.algebra.common.is_spow_enabled` definition unit 

217 tests methods. 

218 """ 

219 

220 def test_is_spow_enabled(self) -> None: 

221 """Test :func:`colour.algebra.common.is_spow_enabled` definition.""" 

222 

223 with spow_enable(True): 

224 assert is_spow_enabled() 

225 

226 with spow_enable(False): 

227 assert not is_spow_enabled() 

228 

229 

230class TestSetSpowEnabled: 

231 """ 

232 Define :func:`colour.algebra.common.set_spow_enable` definition unit 

233 tests methods. 

234 """ 

235 

236 def test_set_spow_enable(self) -> None: 

237 """Test :func:`colour.algebra.common.set_spow_enable` definition.""" 

238 

239 with spow_enable(is_spow_enabled()): 

240 set_spow_enable(True) 

241 assert is_spow_enabled() 

242 

243 with spow_enable(is_spow_enabled()): 

244 set_spow_enable(False) 

245 assert not is_spow_enabled() 

246 

247 

248class TestSpowEnable: 

249 """ 

250 Define :func:`colour.algebra.common.spow_enable` definition unit 

251 tests methods. 

252 """ 

253 

254 def test_spow_enable(self) -> None: 

255 """Test :func:`colour.algebra.common.spow_enable` definition.""" 

256 

257 with spow_enable(True): 

258 assert is_spow_enabled() 

259 

260 with spow_enable(False): 

261 assert not is_spow_enabled() 

262 

263 @spow_enable(True) 

264 def fn_a() -> None: 

265 """:func:`spow_enable` unit tests :func:`fn_a` definition.""" 

266 

267 assert is_spow_enabled() 

268 

269 fn_a() 

270 

271 @spow_enable(False) 

272 def fn_b() -> None: 

273 """:func:`spow_enable` unit tests :func:`fn_b` definition.""" 

274 

275 assert not is_spow_enabled() 

276 

277 fn_b() 

278 

279 

280class TestSpow: 

281 """ 

282 Define :func:`colour.algebra.common.spow` definition unit 

283 tests methods. 

284 """ 

285 

286 def test_spow(self) -> None: 

287 """Test :func:`colour.algebra.common.spow` definition.""" 

288 

289 assert spow(2, 2) == 4.0 

290 

291 assert spow(-2, 2) == -4.0 

292 

293 np.testing.assert_allclose( 

294 spow([2, -2, -2, 0], [2, 2, 0.15, 0]), 

295 np.array([4.00000000, -4.00000000, -1.10956947, 0.00000000]), 

296 atol=TOLERANCE_ABSOLUTE_TESTS, 

297 ) 

298 

299 with spow_enable(True): 

300 np.testing.assert_allclose( 

301 spow(-2, 0.15), -1.10956947, atol=TOLERANCE_ABSOLUTE_TESTS 

302 ) 

303 

304 with spow_enable(False): 

305 np.testing.assert_equal(spow(-2, 0.15), np.nan) 

306 

307 

308class TestNormaliseVector: 

309 """ 

310 Define :func:`colour.algebra.common.normalise_vector` definition unit 

311 tests methods. 

312 """ 

313 

314 def test_normalise_vector(self) -> None: 

315 """Test :func:`colour.algebra.common.normalise_vector` definition.""" 

316 

317 np.testing.assert_allclose( 

318 normalise_vector(np.array([0.20654008, 0.12197225, 0.05136952])), 

319 np.array([0.84197033, 0.49722560, 0.20941026]), 

320 atol=TOLERANCE_ABSOLUTE_TESTS, 

321 ) 

322 

323 np.testing.assert_allclose( 

324 normalise_vector(np.array([0.14222010, 0.23042768, 0.10495772])), 

325 np.array([0.48971705, 0.79344877, 0.36140872]), 

326 atol=TOLERANCE_ABSOLUTE_TESTS, 

327 ) 

328 

329 np.testing.assert_allclose( 

330 normalise_vector(np.array([0.07818780, 0.06157201, 0.28099326])), 

331 np.array([0.26229003, 0.20655044, 0.94262445]), 

332 atol=TOLERANCE_ABSOLUTE_TESTS, 

333 ) 

334 

335 

336class TestNormaliseMaximum: 

337 """ 

338 Define :func:`colour.algebra.common.normalise_maximum` definition unit 

339 tests methods. 

340 """ 

341 

342 def test_normalise_maximum(self) -> None: 

343 """Test :func:`colour.algebra.common.normalise_maximum` definition.""" 

344 

345 np.testing.assert_allclose( 

346 normalise_maximum(np.array([0.20654008, 0.12197225, 0.05136952])), 

347 np.array([1.00000000, 0.59055003, 0.24871454]), 

348 atol=TOLERANCE_ABSOLUTE_TESTS, 

349 ) 

350 

351 np.testing.assert_allclose( 

352 normalise_maximum( 

353 np.array( 

354 [ 

355 [0.20654008, 0.12197225, 0.05136952], 

356 [0.14222010, 0.23042768, 0.10495772], 

357 [0.07818780, 0.06157201, 0.28099326], 

358 ] 

359 ) 

360 ), 

361 np.array( 

362 [ 

363 [0.73503571, 0.43407536, 0.18281406], 

364 [0.50613349, 0.82004700, 0.37352398], 

365 [0.27825507, 0.21912273, 1.00000000], 

366 ] 

367 ), 

368 atol=TOLERANCE_ABSOLUTE_TESTS, 

369 ) 

370 

371 np.testing.assert_allclose( 

372 normalise_maximum( 

373 np.array( 

374 [ 

375 [0.20654008, 0.12197225, 0.05136952], 

376 [0.14222010, 0.23042768, 0.10495772], 

377 [0.07818780, 0.06157201, 0.28099326], 

378 ] 

379 ), 

380 axis=-1, 

381 ), 

382 np.array( 

383 [ 

384 [1.00000000, 0.59055003, 0.24871454], 

385 [0.61720059, 1.00000000, 0.45549094], 

386 [0.27825507, 0.21912273, 1.00000000], 

387 ] 

388 ), 

389 atol=TOLERANCE_ABSOLUTE_TESTS, 

390 ) 

391 

392 np.testing.assert_allclose( 

393 normalise_maximum( 

394 np.array([0.20654008, 0.12197225, 0.05136952]), factor=10 

395 ), 

396 np.array([10.00000000, 5.90550028, 2.48714535]), 

397 atol=TOLERANCE_ABSOLUTE_TESTS, 

398 ) 

399 

400 np.testing.assert_allclose( 

401 normalise_maximum(np.array([-0.11518475, -0.10080000, 0.05089373])), 

402 np.array([0.00000000, 0.00000000, 1.00000000]), 

403 atol=TOLERANCE_ABSOLUTE_TESTS, 

404 ) 

405 

406 np.testing.assert_allclose( 

407 normalise_maximum( 

408 np.array([-0.20654008, -0.12197225, 0.05136952]), clip=False 

409 ), 

410 np.array([-4.02067374, -2.37440899, 1.00000000]), 

411 atol=TOLERANCE_ABSOLUTE_TESTS, 

412 ) 

413 

414 

415class TestVectorDot: 

416 """ 

417 Define :func:`colour.algebra.common.vecmul` definition unit tests 

418 methods. 

419 """ 

420 

421 def test_vecmul(self) -> None: 

422 """Test :func:`colour.algebra.common.vecmul` definition.""" 

423 

424 m = np.array( 

425 [ 

426 [0.7328, 0.4296, -0.1624], 

427 [-0.7036, 1.6975, 0.0061], 

428 [0.0030, 0.0136, 0.9834], 

429 ] 

430 ) 

431 m = np.reshape(np.tile(m, (6, 1)), (6, 3, 3)) 

432 

433 v = np.array([0.20654008, 0.12197225, 0.05136952]) 

434 v = np.tile(v, (6, 1)) 

435 

436 np.testing.assert_allclose( 

437 vecmul(m, v), 

438 np.array( 

439 [ 

440 [0.19540944, 0.06203965, 0.05279523], 

441 [0.19540944, 0.06203965, 0.05279523], 

442 [0.19540944, 0.06203965, 0.05279523], 

443 [0.19540944, 0.06203965, 0.05279523], 

444 [0.19540944, 0.06203965, 0.05279523], 

445 [0.19540944, 0.06203965, 0.05279523], 

446 ] 

447 ), 

448 atol=TOLERANCE_ABSOLUTE_TESTS, 

449 ) 

450 

451 

452class TestEuclideanDistance: 

453 """ 

454 Define :func:`colour.algebra.common.euclidean_distance` definition unit 

455 tests methods. 

456 """ 

457 

458 def test_euclidean_distance(self) -> None: 

459 """Test :func:`colour.algebra.common.euclidean_distance` definition.""" 

460 

461 np.testing.assert_allclose( 

462 euclidean_distance( 

463 np.array([100.00000000, 21.57210357, 272.22819350]), 

464 np.array([100.00000000, 426.67945353, 72.39590835]), 

465 ), 

466 451.71330197, 

467 atol=TOLERANCE_ABSOLUTE_TESTS, 

468 ) 

469 

470 np.testing.assert_allclose( 

471 euclidean_distance( 

472 np.array([100.00000000, 21.57210357, 272.22819350]), 

473 np.array([100.00000000, 74.05216981, 276.45318193]), 

474 ), 

475 52.64986116, 

476 atol=TOLERANCE_ABSOLUTE_TESTS, 

477 ) 

478 

479 np.testing.assert_allclose( 

480 euclidean_distance( 

481 np.array([100.00000000, 21.57210357, 272.22819350]), 

482 np.array([100.00000000, 8.32281957, -73.58297716]), 

483 ), 

484 346.06489172, 

485 atol=TOLERANCE_ABSOLUTE_TESTS, 

486 ) 

487 

488 def test_n_dimensional_euclidean_distance(self) -> None: 

489 """ 

490 Test :func:`colour.algebra.common.euclidean_distance` definition 

491 n-dimensional arrays support. 

492 """ 

493 

494 a = np.array([100.00000000, 21.57210357, 272.22819350]) 

495 b = np.array([100.00000000, 426.67945353, 72.39590835]) 

496 distance = euclidean_distance(a, b) 

497 

498 a = np.tile(a, (6, 1)) 

499 b = np.tile(b, (6, 1)) 

500 distance = np.tile(distance, 6) 

501 np.testing.assert_allclose( 

502 euclidean_distance(a, b), distance, atol=TOLERANCE_ABSOLUTE_TESTS 

503 ) 

504 

505 a = np.reshape(a, (2, 3, 3)) 

506 b = np.reshape(b, (2, 3, 3)) 

507 distance = np.reshape(distance, (2, 3)) 

508 np.testing.assert_allclose( 

509 euclidean_distance(a, b), distance, atol=TOLERANCE_ABSOLUTE_TESTS 

510 ) 

511 

512 @ignore_numpy_errors 

513 def test_nan_euclidean_distance(self) -> None: 

514 """ 

515 Test :func:`colour.algebra.common.euclidean_distance` definition nan 

516 support. 

517 """ 

518 

519 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] 

520 cases = np.array(list(set(product(cases, repeat=3)))) 

521 euclidean_distance(cases, cases) 

522 

523 

524class TestManhattanDistance: 

525 """ 

526 Define :func:`colour.algebra.common.manhattan_distance` definition unit 

527 tests methods. 

528 """ 

529 

530 def test_manhattan_distance(self) -> None: 

531 """Test :func:`colour.algebra.common.manhattan_distance` definition.""" 

532 

533 np.testing.assert_allclose( 

534 manhattan_distance( 

535 np.array([100.00000000, 21.57210357, 272.22819350]), 

536 np.array([100.00000000, 426.67945353, 72.39590835]), 

537 ), 

538 604.93963510999993, 

539 atol=TOLERANCE_ABSOLUTE_TESTS, 

540 ) 

541 

542 np.testing.assert_allclose( 

543 manhattan_distance( 

544 np.array([100.00000000, 21.57210357, 272.22819350]), 

545 np.array([100.00000000, 74.05216981, 276.45318193]), 

546 ), 

547 56.705054670000052, 

548 atol=TOLERANCE_ABSOLUTE_TESTS, 

549 ) 

550 

551 np.testing.assert_allclose( 

552 manhattan_distance( 

553 np.array([100.00000000, 21.57210357, 272.22819350]), 

554 np.array([100.00000000, 8.32281957, -73.58297716]), 

555 ), 

556 359.06045465999995, 

557 atol=TOLERANCE_ABSOLUTE_TESTS, 

558 ) 

559 

560 def test_n_dimensional_manhattan_distance(self) -> None: 

561 """ 

562 Test :func:`colour.algebra.common.manhattan_distance` definition 

563 n-dimensional arrays support. 

564 """ 

565 

566 a = np.array([100.00000000, 21.57210357, 272.22819350]) 

567 b = np.array([100.00000000, 426.67945353, 72.39590835]) 

568 distance = manhattan_distance(a, b) 

569 

570 a = np.tile(a, (6, 1)) 

571 b = np.tile(b, (6, 1)) 

572 distance = np.tile(distance, 6) 

573 np.testing.assert_allclose( 

574 manhattan_distance(a, b), distance, atol=TOLERANCE_ABSOLUTE_TESTS 

575 ) 

576 

577 a = np.reshape(a, (2, 3, 3)) 

578 b = np.reshape(b, (2, 3, 3)) 

579 distance = np.reshape(distance, (2, 3)) 

580 np.testing.assert_allclose( 

581 manhattan_distance(a, b), distance, atol=TOLERANCE_ABSOLUTE_TESTS 

582 ) 

583 

584 @ignore_numpy_errors 

585 def test_nan_manhattan_distance(self) -> None: 

586 """ 

587 Test :func:`colour.algebra.common.manhattan_distance` definition nan 

588 support. 

589 """ 

590 

591 cases = [-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan] 

592 cases = np.array(list(set(product(cases, repeat=3)))) 

593 manhattan_distance(cases, cases) 

594 

595 

596class TestLinearConversion: 

597 """ 

598 Define :func:`colour.algebra.common.linear_conversion` definition unit 

599 tests methods. 

600 """ 

601 

602 def test_linear_conversion(self) -> None: 

603 """Test :func:`colour.algebra.common.linear_conversion` definition.""" 

604 

605 np.testing.assert_allclose( 

606 linear_conversion( 

607 np.linspace(0, 1, 10), np.array([0, 1]), np.array([1, np.pi]) 

608 ), 

609 np.array( 

610 [ 

611 1.00000000, 

612 1.23795474, 

613 1.47590948, 

614 1.71386422, 

615 1.95181896, 

616 2.18977370, 

617 2.42772844, 

618 2.66568318, 

619 2.90363791, 

620 3.14159265, 

621 ] 

622 ), 

623 atol=TOLERANCE_ABSOLUTE_TESTS, 

624 ) 

625 

626 

627class TestLinstepFunction: 

628 """ 

629 Define :func:`colour.algebra.common.linstep_function` definition unit 

630 tests methods. 

631 """ 

632 

633 def test_linstep_function(self) -> None: 

634 """Test :func:`colour.algebra.common.linstep_function` definition.""" 

635 

636 np.testing.assert_allclose( 

637 linstep_function( 

638 np.linspace(0, 1, 10), 

639 np.linspace(0, 1, 10), 

640 np.linspace(0, 2, 10), 

641 ), 

642 np.array( 

643 [ 

644 0.00000000, 

645 0.12345679, 

646 0.27160494, 

647 0.44444444, 

648 0.64197531, 

649 0.86419753, 

650 1.11111111, 

651 1.38271605, 

652 1.67901235, 

653 2.00000000, 

654 ] 

655 ), 

656 atol=TOLERANCE_ABSOLUTE_TESTS, 

657 ) 

658 

659 np.testing.assert_allclose( 

660 linstep_function( 

661 np.linspace(0, 2, 10), 

662 np.linspace(0.25, 0.5, 10), 

663 np.linspace(0.5, 0.75, 10), 

664 clip=True, 

665 ), 

666 np.array( 

667 [ 

668 0.25000000, 

669 0.33333333, 

670 0.41666667, 

671 0.50000000, 

672 0.58333333, 

673 0.63888889, 

674 0.66666667, 

675 0.69444444, 

676 0.72222222, 

677 0.75000000, 

678 ] 

679 ), 

680 atol=TOLERANCE_ABSOLUTE_TESTS, 

681 ) 

682 

683 

684class TestSmoothstepFunction: 

685 """ 

686 Define :func:`colour.algebra.common.smoothstep_function` definition unit 

687 tests methods. 

688 """ 

689 

690 def test_smoothstep_function(self) -> None: 

691 """Test :func:`colour.algebra.common.smoothstep_function` definition.""" 

692 

693 assert smoothstep_function(0.5) == 0.5 

694 assert smoothstep_function(0.25) == 0.15625 

695 assert smoothstep_function(0.75) == 0.84375 

696 

697 x = np.linspace(-2, 2, 5) 

698 np.testing.assert_allclose( 

699 smoothstep_function(x), 

700 np.array([28.00000, 5.00000, 0.00000, 1.00000, -4.00000]), 

701 atol=TOLERANCE_ABSOLUTE_TESTS, 

702 ) 

703 np.testing.assert_allclose( 

704 smoothstep_function(x, -2, 2, clip=True), 

705 np.array([0.00000, 0.15625, 0.50000, 0.84375, 1.00000]), 

706 atol=TOLERANCE_ABSOLUTE_TESTS, 

707 ) 

708 

709 

710class TestIsIdentity: 

711 """ 

712 Define :func:`colour.algebra.common.is_identity` definition unit tests 

713 methods. 

714 """ 

715 

716 def test_is_identity(self) -> None: 

717 """Test :func:`colour.algebra.common.is_identity` definition.""" 

718 

719 assert is_identity(np.reshape(np.array([1, 0, 0, 0, 1, 0, 0, 0, 1]), (3, 3))) 

720 

721 assert not is_identity( 

722 np.reshape(np.array([1, 2, 0, 0, 1, 0, 0, 0, 1]), (3, 3)) 

723 ) 

724 

725 assert is_identity(np.reshape(np.array([1, 0, 0, 1]), (2, 2))) 

726 

727 assert not is_identity(np.reshape(np.array([1, 2, 0, 1]), (2, 2))) 

728 

729 

730class TestEigenDecomposition: 

731 """ 

732 Define :func:`colour.algebra.common.eigen_decomposition` definition unit 

733 tests methods. 

734 """ 

735 

736 def test_is_identity(self) -> None: 

737 """Test :func:`colour.algebra.common.eigen_decomposition` definition.""" 

738 

739 a = np.diag([1, 2, 3]) 

740 

741 w, v = eigen_decomposition(a) 

742 np.testing.assert_equal(w, np.array([3.0, 2.0, 1.0])) 

743 np.testing.assert_equal( 

744 v, np.array([[0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0]]) 

745 ) 

746 

747 w, v = eigen_decomposition(a, 1) 

748 np.testing.assert_equal(w, np.array([3.0])) 

749 np.testing.assert_equal(v, np.array([[0.0], [0.0], [1.0]])) 

750 

751 w, v = eigen_decomposition(a, descending_order=False) 

752 np.testing.assert_equal(w, np.array([1.0, 2.0, 3.0])) 

753 np.testing.assert_equal( 

754 v, np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) 

755 ) 

756 

757 w, v = eigen_decomposition(a, covariance_matrix=True) 

758 np.testing.assert_equal(w, np.array([9.0, 4.0, 1.0])) 

759 np.testing.assert_equal( 

760 v, np.array([[0.0, 0.0, 1.0], [0.0, 1.0, 0.0], [1.0, 0.0, 0.0]]) 

761 ) 

762 

763 w, v = eigen_decomposition(a, descending_order=False, covariance_matrix=True) 

764 np.testing.assert_equal(w, np.array([1.0, 4.0, 9.0])) 

765 np.testing.assert_equal( 

766 v, np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]) 

767 )