/src/libreoffice/include/basegfx/numeric/ftools.hxx
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #pragma once |
21 | | |
22 | | #include <rtl/math.h> |
23 | | #include <cmath> |
24 | | #include <math.h> |
25 | | #include <basegfx/basegfxdllapi.h> |
26 | | #include <limits> |
27 | | #include <algorithm> |
28 | | |
29 | | |
30 | | // fTools defines |
31 | | |
32 | | namespace basegfx |
33 | | { |
34 | | /** Round double to nearest integer |
35 | | |
36 | | @return the nearest integer |
37 | | */ |
38 | | template <class Int = sal_Int32> requires std::is_integral_v<Int> |
39 | | inline Int fround(double fVal) |
40 | 874M | { |
41 | 874M | if (fVal >= 0.0) |
42 | 384M | { |
43 | 384M | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) |
44 | 2.72M | return std::numeric_limits<Int>::max(); |
45 | 382M | return static_cast<Int>(fVal + .5); |
46 | 384M | } |
47 | 489M | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) |
48 | 2.10M | return std::numeric_limits<Int>::min(); |
49 | 487M | return static_cast<Int>(fVal - .5); |
50 | 489M | } _ZN7basegfx6froundIlQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 600M | { | 41 | 600M | if (fVal >= 0.0) | 42 | 225M | { | 43 | 225M | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 214k | return std::numeric_limits<Int>::max(); | 45 | 225M | return static_cast<Int>(fVal + .5); | 46 | 225M | } | 47 | 375M | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 504k | return std::numeric_limits<Int>::min(); | 49 | 375M | return static_cast<Int>(fVal - .5); | 50 | 375M | } |
_ZN7basegfx6froundIhQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 82.4k | { | 41 | 82.4k | if (fVal >= 0.0) | 42 | 64.5k | { | 43 | 64.5k | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 29.5k | return std::numeric_limits<Int>::max(); | 45 | 34.9k | return static_cast<Int>(fVal + .5); | 46 | 64.5k | } | 47 | 17.8k | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 17.8k | return std::numeric_limits<Int>::min(); | 49 | 0 | return static_cast<Int>(fVal - .5); | 50 | 17.8k | } |
_ZN7basegfx6froundIiQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 273M | { | 41 | 273M | if (fVal >= 0.0) | 42 | 159M | { | 43 | 159M | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 2.47M | return std::numeric_limits<Int>::max(); | 45 | 157M | return static_cast<Int>(fVal + .5); | 46 | 159M | } | 47 | 113M | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 1.58M | return std::numeric_limits<Int>::min(); | 49 | 112M | return static_cast<Int>(fVal - .5); | 50 | 113M | } |
_ZN7basegfx6froundIjQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 1.20k | { | 41 | 1.20k | if (fVal >= 0.0) | 42 | 1.20k | { | 43 | 1.20k | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 0 | return std::numeric_limits<Int>::max(); | 45 | 1.20k | return static_cast<Int>(fVal + .5); | 46 | 1.20k | } | 47 | 0 | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 0 | return std::numeric_limits<Int>::min(); | 49 | 0 | return static_cast<Int>(fVal - .5); | 50 | 0 | } |
Unexecuted instantiation: _ZN7basegfx6froundIsQsr3stdE13is_integral_vIT_EEES1_d |
51 | | |
52 | | /** Round double to nearest integer |
53 | | |
54 | | @return the nearest 64 bit integer |
55 | | */ |
56 | 0 | inline sal_Int64 fround64(double fVal) { return fround<sal_Int64>(fVal); } |
57 | | |
58 | | /** Prune a small epsilon range around zero. |
59 | | |
60 | | Use this method e.g. for calculating scale values. There, it |
61 | | is usually advisable not to set a scaling to 0.0, because that |
62 | | yields singular transformation matrices. |
63 | | |
64 | | @param fVal |
65 | | An arbitrary, but finite and valid number |
66 | | |
67 | | @return either fVal, or a small value slightly above (when |
68 | | fVal>0) or below (when fVal<0) zero. |
69 | | */ |
70 | | inline double pruneScaleValue( double fVal ) |
71 | 0 | { |
72 | 0 | if(fVal < 0.0) |
73 | 0 | return std::min(fVal, -0.00001); |
74 | 0 | else |
75 | 0 | return std::max(fVal, 0.00001); |
76 | 0 | } |
77 | | |
78 | | /** Convert value from degrees to radians |
79 | | */ |
80 | | template <int DegMultiple = 1> constexpr double deg2rad( double v ) |
81 | 20.4M | { |
82 | | // divide first, to get exact values for v being a multiple of |
83 | | // 90 degrees |
84 | 20.4M | return v / (90.0 * DegMultiple) * M_PI_2; |
85 | 20.4M | } double basegfx::deg2rad<1>(double) Line | Count | Source | 81 | 6.54M | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | 6.54M | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 6.54M | } |
double basegfx::deg2rad<10>(double) Line | Count | Source | 81 | 13.2M | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | 13.2M | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 13.2M | } |
double basegfx::deg2rad<65536>(double) Line | Count | Source | 81 | 82.6k | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | 82.6k | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 82.6k | } |
double basegfx::deg2rad<100>(double) Line | Count | Source | 81 | 432k | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | 432k | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 432k | } |
double basegfx::deg2rad<60000>(double) Line | Count | Source | 81 | 85.0k | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | 85.0k | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 85.0k | } |
|
86 | | |
87 | | /** Convert value radians to degrees |
88 | | */ |
89 | | template <int DegMultiple = 1> constexpr double rad2deg( double v ) |
90 | 2.08M | { |
91 | | // divide first, to get exact values for v being a multiple of |
92 | | // pi/2 |
93 | 2.08M | return v / M_PI_2 * (90.0 * DegMultiple); |
94 | 2.08M | } double basegfx::rad2deg<10>(double) Line | Count | Source | 90 | 125k | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | 125k | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 125k | } |
double basegfx::rad2deg<1>(double) Line | Count | Source | 90 | 1.79M | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | 1.79M | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 1.79M | } |
double basegfx::rad2deg<100>(double) Line | Count | Source | 90 | 87.3k | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | 87.3k | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 87.3k | } |
double basegfx::rad2deg<60000>(double) Line | Count | Source | 90 | 82.4k | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | 82.4k | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 82.4k | } |
|
95 | | |
96 | | /** Snap v to nearest multiple of fStep, from negative and |
97 | | positive side. |
98 | | |
99 | | Examples: |
100 | | |
101 | | snapToNearestMultiple(-0.1, 0.5) = 0.0 |
102 | | snapToNearestMultiple(0.1, 0.5) = 0.0 |
103 | | snapToNearestMultiple(0.25, 0.5) = 0.0 |
104 | | snapToNearestMultiple(0.26, 0.5) = 0.5 |
105 | | */ |
106 | | BASEGFX_DLLPUBLIC double snapToNearestMultiple(double v, const double fStep); |
107 | | |
108 | | /** Snap v to the range [0.0 .. fWidth] using modulo |
109 | | */ |
110 | | BASEGFX_DLLPUBLIC double snapToZeroRange(double v, double fWidth); |
111 | | |
112 | | /** Snap v to the range [fLow .. fHigh] using modulo |
113 | | */ |
114 | | double snapToRange(double v, double fLow, double fHigh); |
115 | | |
116 | | /** return fValue with the sign of fSignCarrier, thus evtl. changed |
117 | | */ |
118 | | inline double copySign(double fValue, double fSignCarrier) |
119 | 0 | { |
120 | 0 | #ifdef _WIN32 |
121 | 0 | return _copysign(fValue, fSignCarrier); |
122 | 0 | #else |
123 | 0 | return copysign(fValue, fSignCarrier); |
124 | 0 | #endif |
125 | 0 | } |
126 | | |
127 | | /** RotateFlyFrame3: Normalize to range defined by [0.0 ... fRange[, independent |
128 | | if v is positive or negative. |
129 | | |
130 | | Examples: |
131 | | |
132 | | normalizeToRange(0.5, -1.0) = 0.0 |
133 | | normalizeToRange(0.5, 0.0) = 0.0 |
134 | | normalizeToRange(0.5, 1.0) = 0.5 |
135 | | normalizeToRange(-0.5, 1.0) = 0.5 |
136 | | normalizeToRange(-0.3, 1.0) = 0.7 |
137 | | normalizeToRange(-0.7, 1.0) = 0.3 |
138 | | normalizeToRange(3.5, 1.0) = 0.5 |
139 | | normalizeToRange(3.3, 1.0) = 0.3 |
140 | | normalizeToRange(3.7, 1.0) = 0.7 |
141 | | normalizeToRange(-3.5, 1.0) = 0.5 |
142 | | normalizeToRange(-3.3, 1.0) = 0.7 |
143 | | normalizeToRange(-3.7, 1.0) = 0.3 |
144 | | */ |
145 | | BASEGFX_DLLPUBLIC double normalizeToRange(double v, const double fRange); |
146 | | |
147 | | namespace fTools |
148 | | { |
149 | | /// Get threshold value for equalZero and friends |
150 | 992M | inline double getSmallValue() { return 0.000000001f; } |
151 | | |
152 | | /// Compare against small value |
153 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
154 | | inline bool equalZero(const T& rfVal) |
155 | 992M | { |
156 | 992M | return (fabs(rfVal) <= getSmallValue()); |
157 | 992M | } |
158 | | |
159 | | /// Compare against given small value |
160 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
161 | | inline bool equalZero(const T& rfVal, const T& rfSmallValue) |
162 | 3 | { |
163 | 3 | return (fabs(rfVal) <= rfSmallValue); |
164 | 3 | } |
165 | | |
166 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
167 | | inline bool equal(T const& rfValA, T const& rfValB) |
168 | 7.12G | { |
169 | | // changed to approxEqual usage for better numerical correctness |
170 | 7.12G | return rtl_math_approxEqual(rfValA, rfValB); |
171 | 7.12G | } |
172 | | |
173 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
174 | | inline bool equal(const T& rfValA, const T& rfValB, const T& rfSmallValue) |
175 | 0 | { |
176 | 0 | return (fabs(rfValA - rfValB) <= rfSmallValue); |
177 | 0 | } |
178 | | |
179 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
180 | | inline bool less(const T& rfValA, const T& rfValB) |
181 | 12.5M | { |
182 | 12.5M | return (rfValA < rfValB && !equal(rfValA, rfValB)); |
183 | 12.5M | } |
184 | | |
185 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
186 | | inline bool lessOrEqual(const T& rfValA, const T& rfValB) |
187 | 295k | { |
188 | 295k | return (rfValA < rfValB || equal(rfValA, rfValB)); |
189 | 295k | } |
190 | | |
191 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
192 | | inline bool more(const T& rfValA, const T& rfValB) |
193 | 16.8M | { |
194 | 16.8M | return (rfValA > rfValB && !equal(rfValA, rfValB)); |
195 | 16.8M | } |
196 | | |
197 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
198 | | inline bool moreOrEqual(const T& rfValA, const T& rfValB) |
199 | 3.41M | { |
200 | 3.41M | return (rfValA > rfValB || equal(rfValA, rfValB)); |
201 | 3.41M | } |
202 | | |
203 | | template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> |
204 | | inline bool betweenOrEqualEither(const T& rfValA, const T& rfValB, const T& rfValC) |
205 | 14.7M | { |
206 | 14.7M | return (rfValA > rfValB && rfValA < rfValC) || equal(rfValA, rfValB) || equal(rfValA, rfValC); |
207 | 14.7M | } |
208 | | }; |
209 | | } // end of namespace basegfx |
210 | | |
211 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |