Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #ifndef MUSE_GLOBAL_REALFN_H
23 : #define MUSE_GLOBAL_REALFN_H
24 :
25 : #include <cmath>
26 : #include <algorithm>
27 : #include <vector>
28 :
29 : namespace muse {
30 : // default
31 : constexpr double COMPARE_DOUBLE_EPSILON(1000000000.0);
32 : constexpr double COMPARE_DOUBLE_NULL(0.000000001);
33 : constexpr float COMPARE_FLOAT_EPSILON(1000000.0);
34 : constexpr float COMPARE_FLOAT_NULL(0.000001F);
35 :
36 : // use
37 : inline double _compare_double_epsilon(COMPARE_DOUBLE_EPSILON);
38 : inline double _compare_double_null(COMPARE_DOUBLE_NULL);
39 : inline double _compare_float_epsilon(COMPARE_FLOAT_EPSILON);
40 : inline double _compare_float_null(COMPARE_FLOAT_NULL);
41 :
42 5152 : inline constexpr int _pow10(int power)
43 : {
44 5152 : int result = 1;
45 11572 : for (int i = 0; i < power; ++i) {
46 6420 : result *= 10;
47 : }
48 5152 : return result;
49 : }
50 :
51 0 : inline void SetCompareDoublePrecision(int prec)
52 : {
53 0 : _compare_double_epsilon = _pow10(prec);
54 0 : _compare_double_null = 1.0 / _compare_double_epsilon;
55 0 : }
56 :
57 : inline void SetDefaultCompareDoublePrecision()
58 : {
59 : _compare_double_epsilon = COMPARE_DOUBLE_EPSILON;
60 : _compare_double_null = COMPARE_DOUBLE_NULL;
61 : }
62 :
63 0 : inline void SetCompareFloatPrecision(int prec)
64 : {
65 0 : _compare_float_epsilon = _pow10(prec);
66 0 : _compare_float_null = 1.0 / _compare_float_epsilon;
67 0 : }
68 :
69 : inline void SetDefaultCompareFloatPrecision()
70 : {
71 : _compare_float_epsilon = COMPARE_FLOAT_EPSILON;
72 : _compare_float_null = COMPARE_FLOAT_NULL;
73 : }
74 :
75 : // both double and float
76 0 : inline void SetCompareRealPrecision(int prec)
77 : {
78 0 : SetCompareDoublePrecision(prec);
79 0 : SetCompareFloatPrecision(prec);
80 0 : }
81 :
82 : inline void SetDefaultCompareRealPrecision()
83 : {
84 : SetDefaultCompareDoublePrecision();
85 : SetDefaultCompareFloatPrecision();
86 : }
87 :
88 1904827 : inline bool RealIsEqual(double p1, double p2)
89 : {
90 1904827 : return std::abs(p1 - p2) * _compare_double_epsilon <= std::min(std::abs(p1), std::abs(p2));
91 : }
92 :
93 252 : inline bool RealIsEqual(float p1, float p2)
94 : {
95 252 : return std::fabs(p1 - p2) * _compare_float_epsilon <= std::min(std::fabs(p1), std::fabs(p2));
96 : }
97 :
98 2 : inline bool RealIsEqual(const std::vector<double>& v1, const std::vector<double>& v2)
99 : {
100 2 : if (v1.size() != v2.size()) {
101 0 : return false;
102 : }
103 :
104 2 : for (size_t i = 0; i < v1.size(); ++i) {
105 0 : if (!RealIsEqual(v1.at(i), v2.at(i))) {
106 0 : return false;
107 : }
108 : }
109 :
110 2 : return true;
111 : }
112 :
113 : inline bool RealIsEqual(const std::vector<float>& v1, const std::vector<float>& v2)
114 : {
115 : if (v1.size() != v2.size()) {
116 : return false;
117 : }
118 :
119 : for (size_t i = 0; i < v1.size(); ++i) {
120 : if (!RealIsEqual(v1.at(i), v2.at(i))) {
121 : return false;
122 : }
123 : }
124 :
125 : return true;
126 : }
127 :
128 600890 : inline bool RealIsEqualOrMore(double p1, double p2)
129 : {
130 600890 : return p1 > p2 || RealIsEqual(p1, p2);
131 : }
132 :
133 457306 : inline bool RealIsEqualOrLess(double p1, double p2)
134 : {
135 457306 : return p1 < p2 || RealIsEqual(p1, p2);
136 : }
137 :
138 0 : inline bool RealIsEqualOrMore(float p1, float p2)
139 : {
140 0 : return p1 > p2 || RealIsEqual(p1, p2);
141 : }
142 :
143 58 : inline bool RealIsEqualOrLess(float p1, float p2)
144 : {
145 58 : return p1 < p2 || RealIsEqual(p1, p2);
146 : }
147 :
148 1297429 : inline bool RealIsNull(double d)
149 : {
150 1297429 : return std::abs(d) <= _compare_double_null;
151 : }
152 :
153 2395 : inline bool RealIsNull(float d)
154 : {
155 2395 : return std::fabs(d) <= _compare_float_null;
156 : }
157 :
158 3632 : inline double RealRound(double value, int prec)
159 : {
160 3632 : int round = _pow10(prec);
161 3632 : return std::floor(value * round + 0.5) / round;
162 : }
163 :
164 3527 : inline double RealRound(float value, int prec)
165 : {
166 3527 : return RealRound(static_cast<double>(value), prec);
167 : }
168 :
169 1520 : inline double RealFloor(double value, int prec)
170 : {
171 1520 : int round = _pow10(prec);
172 1520 : return std::floor(value * round) / round;
173 : }
174 :
175 : inline double RealFloor(float value, int prec)
176 : {
177 : return RealRound(static_cast<double>(value), prec);
178 : }
179 : }
180 :
181 : #endif // MUSE_GLOBAL_REALFN_H
|