/src/libreoffice/include/basegfx/numeric/ftools.hxx
Line | Count | Source |
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 | 432M | { |
41 | 432M | if (fVal >= 0.0) |
42 | 215M | { |
43 | 215M | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) |
44 | 3.67M | return std::numeric_limits<Int>::max(); |
45 | 211M | return static_cast<Int>(fVal + .5); |
46 | 215M | } |
47 | 216M | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) |
48 | 1.10M | return std::numeric_limits<Int>::min(); |
49 | 215M | return static_cast<Int>(fVal - .5); |
50 | 216M | } _ZN7basegfx6froundIlQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 275M | { | 41 | 275M | if (fVal >= 0.0) | 42 | 121M | { | 43 | 121M | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 268k | return std::numeric_limits<Int>::max(); | 45 | 121M | return static_cast<Int>(fVal + .5); | 46 | 121M | } | 47 | 154M | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 283k | return std::numeric_limits<Int>::min(); | 49 | 154M | return static_cast<Int>(fVal - .5); | 50 | 154M | } |
_ZN7basegfx6froundIhQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 41.0k | { | 41 | 41.0k | if (fVal >= 0.0) | 42 | 33.3k | { | 43 | 33.3k | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 13.3k | return std::numeric_limits<Int>::max(); | 45 | 20.0k | return static_cast<Int>(fVal + .5); | 46 | 33.3k | } | 47 | 7.65k | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 7.65k | return std::numeric_limits<Int>::min(); | 49 | 0 | return static_cast<Int>(fVal - .5); | 50 | 7.65k | } |
_ZN7basegfx6froundIiQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 156M | { | 41 | 156M | if (fVal >= 0.0) | 42 | 94.0M | { | 43 | 94.0M | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 3.38M | return std::numeric_limits<Int>::max(); | 45 | 90.6M | return static_cast<Int>(fVal + .5); | 46 | 94.0M | } | 47 | 62.1M | if (fVal <= static_cast<double>(std::numeric_limits<Int>::min()) + 0.5) | 48 | 817k | return std::numeric_limits<Int>::min(); | 49 | 61.3M | return static_cast<Int>(fVal - .5); | 50 | 62.1M | } |
_ZN7basegfx6froundIjQsr3stdE13is_integral_vIT_EEES1_d Line | Count | Source | 40 | 972 | { | 41 | 972 | if (fVal >= 0.0) | 42 | 972 | { | 43 | 972 | if (fVal >= static_cast<double>(std::numeric_limits<Int>::max()) - 0.5) | 44 | 0 | return std::numeric_limits<Int>::max(); | 45 | 972 | return static_cast<Int>(fVal + .5); | 46 | 972 | } | 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 | 21.7M | { |
82 | | // divide first, to get exact values for v being a multiple of |
83 | | // 90 degrees |
84 | 21.7M | return v / (90.0 * DegMultiple) * M_PI_2; |
85 | 21.7M | } double basegfx::deg2rad<1>(double) Line | Count | Source | 81 | 9.03M | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 9.03M | } |
double basegfx::deg2rad<10>(double) Line | Count | Source | 81 | 12.2M | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 12.2M | } |
double basegfx::deg2rad<65536>(double) Line | Count | Source | 81 | 61.2k | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 61.2k | } |
double basegfx::deg2rad<100>(double) Line | Count | Source | 81 | 369k | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 369k | } |
double basegfx::deg2rad<60000>(double) Line | Count | Source | 81 | 74.1k | { | 82 | | // divide first, to get exact values for v being a multiple of | 83 | | // 90 degrees | 84 | | return v / (90.0 * DegMultiple) * M_PI_2; | 85 | 74.1k | } |
|
86 | | |
87 | | /** Convert value radians to degrees |
88 | | */ |
89 | | template <int DegMultiple = 1> constexpr double rad2deg( double v ) |
90 | 1.53M | { |
91 | | // divide first, to get exact values for v being a multiple of |
92 | | // pi/2 |
93 | 1.53M | return v / M_PI_2 * (90.0 * DegMultiple); |
94 | 1.53M | } double basegfx::rad2deg<10>(double) Line | Count | Source | 90 | 97.7k | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 97.7k | } |
double basegfx::rad2deg<1>(double) Line | Count | Source | 90 | 1.29M | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 1.29M | } |
double basegfx::rad2deg<100>(double) Line | Count | Source | 90 | 69.7k | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 69.7k | } |
double basegfx::rad2deg<60000>(double) Line | Count | Source | 90 | 72.0k | { | 91 | | // divide first, to get exact values for v being a multiple of | 92 | | // pi/2 | 93 | | return v / M_PI_2 * (90.0 * DegMultiple); | 94 | 72.0k | } |
|
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 | 504M | 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 | 504M | { |
156 | 504M | return (fabs(rfVal) <= getSmallValue()); |
157 | 504M | } |
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 | 2.26G | { |
169 | | // changed to approxEqual usage for better numerical correctness |
170 | 2.26G | return rtl_math_approxEqual(rfValA, rfValB); |
171 | 2.26G | } |
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 | 17.9M | { |
182 | 17.9M | return (rfValA < rfValB && !equal(rfValA, rfValB)); |
183 | 17.9M | } |
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 | 111k | { |
188 | 111k | return (rfValA < rfValB || equal(rfValA, rfValB)); |
189 | 111k | } |
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 | 25.1M | { |
194 | 25.1M | return (rfValA > rfValB && !equal(rfValA, rfValB)); |
195 | 25.1M | } |
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 | 2.06M | { |
200 | 2.06M | return (rfValA > rfValB || equal(rfValA, rfValB)); |
201 | 2.06M | } |
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 | 4.55M | { |
206 | 4.55M | return (rfValA > rfValB && rfValA < rfValC) || equal(rfValA, rfValB) || equal(rfValA, rfValC); |
207 | 4.55M | } |
208 | | }; |
209 | | } // end of namespace basegfx |
210 | | |
211 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |