1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _BGFX_NUMERIC_FTOOLS_HXX
25 #define _BGFX_NUMERIC_FTOOLS_HXX
26 
27 #include <rtl/math.hxx>
28 
29 //////////////////////////////////////////////////////////////////////////////
30 // standard PI defines from solar.h, but we do not want to link against tools
31 
32 #ifndef F_PI
33 #define F_PI		M_PI
34 #endif
35 #ifndef F_PI2
36 #define F_PI2		M_PI_2
37 #endif
38 #ifndef F_PI4
39 #define F_PI4		M_PI_4
40 #endif
41 #ifndef F_PI180
42 #define F_PI180 	(M_PI/180.0)
43 #endif
44 #ifndef F_PI1800
45 #define F_PI1800	(M_PI/1800.0)
46 #endif
47 #ifndef F_PI18000
48 #define F_PI18000	(M_PI/18000.0)
49 #endif
50 #ifndef F_2PI
51 #define F_2PI		(2.0*M_PI)
52 #endif
53 
54 //////////////////////////////////////////////////////////////////////////////
55 // fTools defines
56 
57 namespace basegfx
58 {
59 	/** Round double to nearest integer
60 
61 	    @return the nearest integer
62     */
fround(double fVal)63     inline sal_Int32 fround( double fVal )
64     {
65         return fVal > 0.0 ? static_cast<sal_Int32>( fVal + .5 ) : -static_cast<sal_Int32>( -fVal + .5 );
66     }
67 
68 	/** Round double to nearest integer
69 
70     	@return the nearest 64 bit integer
71     */
fround64(double fVal)72     inline sal_Int64 fround64( double fVal )
73     {
74         return fVal > 0.0 ? static_cast<sal_Int64>( fVal + .5 ) : -static_cast<sal_Int64>( -fVal + .5 );
75     }
76 
77     /** Prune a small epsilon range around zero.
78 
79     	Use this method e.g. for calculating scale values. There, it
80     	is usually advisable not to set a scaling to 0.0, because that
81     	yields singular transformation matrices.
82 
83         @param fVal
84         An arbitrary, but finite and valid number
85 
86         @return either fVal, or a small value slightly above (when
87         fVal>0) or below (when fVal<0) zero.
88      */
pruneScaleValue(double fVal)89     inline double pruneScaleValue( double fVal )
90     {
91 		// old version used ::std::min/max, but this collides if min is defined as preprocessor
92 		// macro which is the case e.g with windows.h headers. The simplest way to avoid this is to
93 		// just use the full comparison. I keep the original here, maybe there will be a better
94 		// solution some day.
95 		//
96         //return fVal < 0.0 ?
97         //    (::std::min(fVal,-0.00001)) :
98         //    (::std::max(fVal,0.00001));
99 
100 		if(fVal < 0.0)
101 			return (fVal < -0.00001 ? fVal : -0.00001);
102 		else
103 			return (fVal > 0.00001 ? fVal : 0.00001);
104     }
105 
106     /** clamp given value against given minimum and maximum values
107     */
clamp(const T & value,const T & minimum,const T & maximum)108     template <class T> inline const T& clamp(const T& value, const T& minimum, const T& maximum)
109     {
110         if(value < minimum)
111         {
112             return minimum;
113         }
114         else if(value > maximum)
115         {
116             return maximum;
117         }
118         else
119         {
120             return value;
121         }
122     }
123 
124     /** Convert value from degrees to radians
125      */
deg2rad(double v)126     inline double deg2rad( double v )
127     {
128         // divide first, to get exact values for v being a multiple of
129         // 90 degrees
130         return v / 90.0 * M_PI_2;
131     }
132 
133     /** Convert value radians to degrees
134      */
rad2deg(double v)135     inline double rad2deg( double v )
136     {
137         // divide first, to get exact values for v being a multiple of
138         // pi/2
139         return v / M_PI_2 * 90.0;
140     }
141 
142     /** Snap v to nearest multiple of fStep, from negative and
143 		positive side.
144 
145 		Examples:
146 
147 		snapToNearestMultiple(-0.1, 0.5) = 0.0
148 		snapToNearestMultiple(0.1, 0.5) = 0.0
149 		snapToNearestMultiple(0.25, 0.5) = 0.0
150 		snapToNearestMultiple(0.26, 0.5) = 0.5
151      */
152 	double snapToNearestMultiple(double v, const double fStep);
153 
154     /** Snap v to the range [0.0 .. fWidth] using modulo
155      */
156 	double snapToZeroRange(double v, double fWidth);
157 
158     /** Snap v to the range [fLow .. fHigh] using modulo
159      */
160 	double snapToRange(double v, double fLow, double fHigh);
161 
162 	/** return fValue with the sign of fSignCarrier, thus evtl. changed
163 	*/
copySign(double fValue,double fSignCarrier)164 	inline double copySign(double fValue, double fSignCarrier)
165 	{
166 #ifdef WNT
167 		return _copysign(fValue, fSignCarrier);
168 #else
169 		return copysign(fValue, fSignCarrier);
170 #endif
171 	}
172 
173     class fTools
174 	{
175         /// Threshold value for equalZero()
176 		static double									mfSmallValue;
177 
178 	public:
179         /// Get threshold value for equalZero and friends
getSmallValue()180 		static double getSmallValue() { return mfSmallValue; }
181         /// Set threshold value for equalZero and friends
setSmallValue(const double & rfNew)182 		static void setSmallValue(const double& rfNew) { mfSmallValue = rfNew; }
183 
184 		/// Compare against small value
equalZero(const double & rfVal)185 		static bool equalZero(const double& rfVal)
186 		{
187 			return (fabs(rfVal) <= getSmallValue());
188 		}
189 
190 		/// Compare against given small value
equalZero(const double & rfVal,const double & rfSmallValue)191 		static bool equalZero(const double& rfVal, const double& rfSmallValue)
192 		{
193 			return (fabs(rfVal) <= rfSmallValue);
194 		}
195 
equal(const double & rfValA,const double & rfValB)196 		static bool equal(const double& rfValA, const double& rfValB)
197 		{
198 			// changed to approxEqual usage for better numerical correctness
199 			return rtl::math::approxEqual(rfValA, rfValB);
200 		}
201 
equal(const double & rfValA,const double & rfValB,const double & rfSmallValue)202 		static bool equal(const double& rfValA, const double& rfValB, const double& rfSmallValue)
203 		{
204 			return (fabs(rfValA - rfValB) <= rfSmallValue);
205 		}
206 
less(const double & rfValA,const double & rfValB)207 		static bool less(const double& rfValA, const double& rfValB)
208 		{
209 			return (rfValA < rfValB && !equal(rfValA, rfValB));
210 		}
211 
lessOrEqual(const double & rfValA,const double & rfValB)212 		static bool lessOrEqual(const double& rfValA, const double& rfValB)
213 		{
214 			return (rfValA < rfValB || equal(rfValA, rfValB));
215 		}
216 
more(const double & rfValA,const double & rfValB)217 		static bool more(const double& rfValA, const double& rfValB)
218 		{
219 			return (rfValA > rfValB && !equal(rfValA, rfValB));
220 		}
221 
moreOrEqual(const double & rfValA,const double & rfValB)222 		static bool moreOrEqual(const double& rfValA, const double& rfValB)
223 		{
224 			return (rfValA > rfValB || equal(rfValA, rfValB));
225 		}
226 	};
227 } // end of namespace basegfx
228 
229 #endif /* _BGFX_NUMERIC_FTOOLS_HXX */
230