File indexing completed on 2024-05-12 04:44:33
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 // Own header 0005 #include "helpermath.h" 0006 0007 #include <optional> 0008 #include <qgenericmatrix.h> 0009 #include <qmath.h> 0010 0011 namespace PerceptualColor 0012 { 0013 0014 /** @internal 0015 * 0016 * @brief Convenience constructor for @ref SquareMatrix3. 0017 * 0018 * @param r0c0 row 0, column 0 0019 * @param r0c1 row 0, column 1 0020 * @param r0c2 row 0, column 2 0021 * @param r1c0 row 1, column 0 0022 * @param r1c1 row 1, column 1 0023 * @param r1c2 row 1, column 2 0024 * @param r2c0 row 2, column 0 0025 * @param r2c1 row 2, column 1 0026 * @param r2c2 row 2, column 2 0027 * 0028 * @returns The corresponding @ref SquareMatrix3. */ 0029 SquareMatrix3 createSquareMatrix3(double r0c0, double r0c1, double r0c2, double r1c0, double r1c1, double r1c2, double r2c0, double r2c1, double r2c2) 0030 { 0031 // clang-format off 0032 const double valueArray[] = {r0c0, r0c1, r0c2, 0033 r1c0, r1c1, r1c2, 0034 r2c0, r2c1, r2c2}; 0035 // clang-format on 0036 return SquareMatrix3(valueArray); 0037 } 0038 0039 /** @internal 0040 * 0041 * @brief Convenience constructor for @ref Trio. 0042 * 0043 * @param first first value 0044 * @param second second value 0045 * @param third third value 0046 * 0047 * @returns The corresponding @ref Trio. */ 0048 Trio createTrio(double first, double second, double third) 0049 { 0050 const double valueArray[] = {first, second, third}; 0051 return Trio(valueArray); 0052 } 0053 0054 /** @internal 0055 * 0056 * @brief Try to find the inverse matrix. 0057 * 0058 * @param matrix The original matrix. 0059 * 0060 * @returns If the original matrix is invertible, its inverse matrix. 0061 * An empty value otherwise. */ 0062 std::optional<SquareMatrix3> inverseMatrix(const SquareMatrix3 &matrix) 0063 { 0064 const double &a = matrix(0, 0); 0065 const double &b = matrix(0, 1); 0066 const double &c = matrix(0, 2); 0067 const double &d = matrix(1, 0); 0068 const double &e = matrix(1, 1); 0069 const double &f = matrix(1, 2); 0070 const double &g = matrix(2, 0); 0071 const double &h = matrix(2, 1); 0072 const double &i = matrix(2, 2); 0073 const auto determinant = a * e * i // 0074 + b * f * g // 0075 + c * d * h // 0076 - c * e * g // 0077 - b * d * i // 0078 - a * f * h; 0079 if (determinant == 0) { 0080 return std::nullopt; 0081 } 0082 // clang-format off 0083 const auto temp = createSquareMatrix3( 0084 e * i - f * h, c * h - b * i, b * f - c * e, 0085 f * g - d * i, a * i - c * g, c * d - a * f, 0086 d * h - e * g, b * g - a * h, a * e - b * d); 0087 // clang-format on 0088 return temp / determinant; 0089 } 0090 0091 /** @brief Calculates the required number of decimals to achieve the requested 0092 * number of significant figures within the given range. 0093 * 0094 * @param rangeMax The maximum value of the range [0, rangeMax]. 0095 * @param significantFigures The requested number of significant figures. 0096 * 0097 * | maxRange | decimalPlaces(maxRange, 2) | decimalPlaces(maxRange, 3) | decimalPlaces(maxRange, 4) | 0098 * | -------: | -------------------------: | -------------------------: | -------------------------: | 0099 * | 1 | 1 | 2 | 3 | 0100 * | 2 | 1 | 2 | 3 | 0101 * | 100 | 0 | 0 | 1 | 0102 * | 255 | 0 | 0 | 1 | 0103 * | 360 | 0 | 0 | 1 | 0104 * 0105 * @returns The number of decimal places after the decimal point (in addition 0106 * to the whole number part) required to achieve the requested 0107 * number of significant figures within the given range. */ 0108 int decimalPlaces(const int rangeMax, const int significantFigures) 0109 { 0110 const auto myLog10Value = std::log10(qAbs(rangeMax)); 0111 const int wholeNumberDigits = (rangeMax == 0) // 0112 ? 1 // special case 0113 : qFloor(myLog10Value) + 1; 0114 return qMax(0, significantFigures - wholeNumberDigits); 0115 } 0116 0117 } // namespace PerceptualColor