# Perceptual Color

helpermath.cpp
3
5#include "helpermath.h"
6
7#include <optional>
8#include <qgenericmatrix.h>
9#include <qmath.h>
10
11namespace PerceptualColor
12{
13
14/** @internal
15 *
16 * @brief Convenience constructor for @ref SquareMatrix3.
17 *
18 * @param r0c0 row 0, column 0
19 * @param r0c1 row 0, column 1
20 * @param r0c2 row 0, column 2
21 * @param r1c0 row 1, column 0
22 * @param r1c1 row 1, column 1
23 * @param r1c2 row 1, column 2
24 * @param r2c0 row 2, column 0
25 * @param r2c1 row 2, column 1
26 * @param r2c2 row 2, column 2
27 *
28 * @returns The corresponding @ref SquareMatrix3. */
29SquareMatrix3 createSquareMatrix3(double r0c0, double r0c1, double r0c2, double r1c0, double r1c1, double r1c2, double r2c0, double r2c1, double r2c2)
30{
31 // clang-format off
32 const double valueArray[] = {r0c0, r0c1, r0c2,
33 r1c0, r1c1, r1c2,
34 r2c0, r2c1, r2c2};
35 // clang-format on
36 return SquareMatrix3(valueArray);
37}
38
39/** @internal
40 *
41 * @brief Convenience constructor for @ref Trio.
42 *
43 * @param first first value
44 * @param second second value
45 * @param third third value
46 *
47 * @returns The corresponding @ref Trio. */
48Trio createTrio(double first, double second, double third)
49{
50 const double valueArray[] = {first, second, third};
51 return Trio(valueArray);
52}
53
54/** @internal
55 *
56 * @brief Try to find the inverse matrix.
57 *
58 * @param matrix The original matrix.
59 *
60 * @returns If the original matrix is invertible, its inverse matrix.
61 * An empty value otherwise. */
62std::optional<SquareMatrix3> inverseMatrix(const SquareMatrix3 &matrix)
63{
64 const double &a = matrix(0, 0);
65 const double &b = matrix(0, 1);
66 const double &c = matrix(0, 2);
67 const double &d = matrix(1, 0);
68 const double &e = matrix(1, 1);
69 const double &f = matrix(1, 2);
70 const double &g = matrix(2, 0);
71 const double &h = matrix(2, 1);
72 const double &i = matrix(2, 2);
73 const auto determinant = a * e * i //
74 + b * f * g //
75 + c * d * h //
76 - c * e * g //
77 - b * d * i //
78 - a * f * h;
79 if (determinant == 0) {
80 return std::nullopt;
81 }
82 // clang-format off
83 const auto temp = createSquareMatrix3(
84 e * i - f * h, c * h - b * i, b * f - c * e,
85 f * g - d * i, a * i - c * g, c * d - a * f,
86 d * h - e * g, b * g - a * h, a * e - b * d);
87 // clang-format on
88 return temp / determinant;
89}
90
91/** @brief Calculates the required number of decimals to achieve the requested
92 * number of significant figures within the given range.
93 *
94 * @param rangeMax The maximum value of the range [0, rangeMax].
95 * @param significantFigures The requested number of significant figures.
96 *
97 * | maxRange | decimalPlaces(maxRange, 2) | decimalPlaces(maxRange, 3) | decimalPlaces(maxRange, 4) |
98 * | -------: | -------------------------: | -------------------------: | -------------------------: |
99 * | 1 | 1 | 2 | 3 |
100 * | 2 | 1 | 2 | 3 |
101 * | 100 | 0 | 0 | 1 |
102 * | 255 | 0 | 0 | 1 |
103 * | 360 | 0 | 0 | 1 |
104 *
105 * @returns The number of decimal places after the decimal point (in addition
106 * to the whole number part) required to achieve the requested
107 * number of significant figures within the given range. */
108int decimalPlaces(const int rangeMax, const int significantFigures)
109{
110 const auto myLog10Value = std::log10(qAbs(rangeMax));
111 const int wholeNumberDigits = (rangeMax == 0) //
112 ? 1 // special case
113 : qFloor(myLog10Value) + 1;
114 return qMax(0, significantFigures - wholeNumberDigits);
115}
116
117} // namespace PerceptualColor
The namespace of this library.
int decimalPlaces(const int rangeMax, const int significantFigures)
Calculates the required number of decimals to achieve the requested number of significant figures wit...
This file is part of the KDE documentation.