xref: /aoo4110/main/sal/inc/rtl/math.hxx (revision b1cdbd2c)
1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski #if !defined INCLUDED_RTL_MATH_HXX
25*b1cdbd2cSJim Jagielski #define INCLUDED_RTL_MATH_HXX
26*b1cdbd2cSJim Jagielski 
27*b1cdbd2cSJim Jagielski #include "rtl/math.h"
28*b1cdbd2cSJim Jagielski #include "rtl/string.hxx"
29*b1cdbd2cSJim Jagielski #include "rtl/ustring.hxx"
30*b1cdbd2cSJim Jagielski #include "rtl/ustrbuf.hxx"
31*b1cdbd2cSJim Jagielski #include "sal/mathconf.h"
32*b1cdbd2cSJim Jagielski #include "sal/types.h"
33*b1cdbd2cSJim Jagielski 
34*b1cdbd2cSJim Jagielski #include <math.h>
35*b1cdbd2cSJim Jagielski 
36*b1cdbd2cSJim Jagielski namespace rtl {
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski namespace math {
39*b1cdbd2cSJim Jagielski 
40*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_doubleToString.
41*b1cdbd2cSJim Jagielski  */
doubleToString(double fValue,rtl_math_StringFormat eFormat,sal_Int32 nDecPlaces,sal_Char cDecSeparator,sal_Int32 const * pGroups,sal_Char cGroupSeparator,bool bEraseTrailingDecZeros=false)42*b1cdbd2cSJim Jagielski inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
43*b1cdbd2cSJim Jagielski                                    sal_Int32 nDecPlaces,
44*b1cdbd2cSJim Jagielski                                    sal_Char cDecSeparator,
45*b1cdbd2cSJim Jagielski                                    sal_Int32 const * pGroups,
46*b1cdbd2cSJim Jagielski                                    sal_Char cGroupSeparator,
47*b1cdbd2cSJim Jagielski                                    bool bEraseTrailingDecZeros = false)
48*b1cdbd2cSJim Jagielski {
49*b1cdbd2cSJim Jagielski     rtl::OString aResult;
50*b1cdbd2cSJim Jagielski     rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
51*b1cdbd2cSJim Jagielski                             cDecSeparator, pGroups, cGroupSeparator,
52*b1cdbd2cSJim Jagielski                             bEraseTrailingDecZeros);
53*b1cdbd2cSJim Jagielski     return aResult;
54*b1cdbd2cSJim Jagielski }
55*b1cdbd2cSJim Jagielski 
56*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_doubleToString, with no grouping.
57*b1cdbd2cSJim Jagielski  */
doubleToString(double fValue,rtl_math_StringFormat eFormat,sal_Int32 nDecPlaces,sal_Char cDecSeparator,bool bEraseTrailingDecZeros=false)58*b1cdbd2cSJim Jagielski inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
59*b1cdbd2cSJim Jagielski                                    sal_Int32 nDecPlaces,
60*b1cdbd2cSJim Jagielski                                    sal_Char cDecSeparator,
61*b1cdbd2cSJim Jagielski                                    bool bEraseTrailingDecZeros = false)
62*b1cdbd2cSJim Jagielski {
63*b1cdbd2cSJim Jagielski     rtl::OString aResult;
64*b1cdbd2cSJim Jagielski     rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
65*b1cdbd2cSJim Jagielski                             cDecSeparator, 0, 0, bEraseTrailingDecZeros);
66*b1cdbd2cSJim Jagielski     return aResult;
67*b1cdbd2cSJim Jagielski }
68*b1cdbd2cSJim Jagielski 
69*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_doubleToUString.
70*b1cdbd2cSJim Jagielski  */
doubleToUString(double fValue,rtl_math_StringFormat eFormat,sal_Int32 nDecPlaces,sal_Unicode cDecSeparator,sal_Int32 const * pGroups,sal_Unicode cGroupSeparator,bool bEraseTrailingDecZeros=false)71*b1cdbd2cSJim Jagielski inline rtl::OUString doubleToUString(double fValue,
72*b1cdbd2cSJim Jagielski                                      rtl_math_StringFormat eFormat,
73*b1cdbd2cSJim Jagielski                                      sal_Int32 nDecPlaces,
74*b1cdbd2cSJim Jagielski                                      sal_Unicode cDecSeparator,
75*b1cdbd2cSJim Jagielski                                      sal_Int32 const * pGroups,
76*b1cdbd2cSJim Jagielski                                      sal_Unicode cGroupSeparator,
77*b1cdbd2cSJim Jagielski                                      bool bEraseTrailingDecZeros = false)
78*b1cdbd2cSJim Jagielski {
79*b1cdbd2cSJim Jagielski     rtl::OUString aResult;
80*b1cdbd2cSJim Jagielski     rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
81*b1cdbd2cSJim Jagielski                              cDecSeparator, pGroups, cGroupSeparator,
82*b1cdbd2cSJim Jagielski                              bEraseTrailingDecZeros);
83*b1cdbd2cSJim Jagielski     return aResult;
84*b1cdbd2cSJim Jagielski }
85*b1cdbd2cSJim Jagielski 
86*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_doubleToUString, with no grouping.
87*b1cdbd2cSJim Jagielski  */
doubleToUString(double fValue,rtl_math_StringFormat eFormat,sal_Int32 nDecPlaces,sal_Unicode cDecSeparator,bool bEraseTrailingDecZeros=false)88*b1cdbd2cSJim Jagielski inline rtl::OUString doubleToUString(double fValue,
89*b1cdbd2cSJim Jagielski                                      rtl_math_StringFormat eFormat,
90*b1cdbd2cSJim Jagielski                                      sal_Int32 nDecPlaces,
91*b1cdbd2cSJim Jagielski                                      sal_Unicode cDecSeparator,
92*b1cdbd2cSJim Jagielski                                      bool bEraseTrailingDecZeros = false)
93*b1cdbd2cSJim Jagielski {
94*b1cdbd2cSJim Jagielski     rtl::OUString aResult;
95*b1cdbd2cSJim Jagielski     rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
96*b1cdbd2cSJim Jagielski                              cDecSeparator, 0, 0, bEraseTrailingDecZeros);
97*b1cdbd2cSJim Jagielski     return aResult;
98*b1cdbd2cSJim Jagielski }
99*b1cdbd2cSJim Jagielski 
100*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_doubleToUString that appends to an
101*b1cdbd2cSJim Jagielski     rtl::OUStringBuffer.
102*b1cdbd2cSJim Jagielski  */
doubleToUStringBuffer(rtl::OUStringBuffer & rBuffer,double fValue,rtl_math_StringFormat eFormat,sal_Int32 nDecPlaces,sal_Unicode cDecSeparator,sal_Int32 const * pGroups,sal_Unicode cGroupSeparator,bool bEraseTrailingDecZeros=false)103*b1cdbd2cSJim Jagielski inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
104*b1cdbd2cSJim Jagielski                                    rtl_math_StringFormat eFormat,
105*b1cdbd2cSJim Jagielski                                    sal_Int32 nDecPlaces,
106*b1cdbd2cSJim Jagielski                                    sal_Unicode cDecSeparator,
107*b1cdbd2cSJim Jagielski                                    sal_Int32 const * pGroups,
108*b1cdbd2cSJim Jagielski                                    sal_Unicode cGroupSeparator,
109*b1cdbd2cSJim Jagielski                                    bool bEraseTrailingDecZeros = false)
110*b1cdbd2cSJim Jagielski {
111*b1cdbd2cSJim Jagielski     rtl_uString ** pData;
112*b1cdbd2cSJim Jagielski     sal_Int32 * pCapacity;
113*b1cdbd2cSJim Jagielski     rBuffer.accessInternals( &pData, &pCapacity );
114*b1cdbd2cSJim Jagielski     rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
115*b1cdbd2cSJim Jagielski                               eFormat, nDecPlaces, cDecSeparator, pGroups,
116*b1cdbd2cSJim Jagielski                               cGroupSeparator, bEraseTrailingDecZeros);
117*b1cdbd2cSJim Jagielski }
118*b1cdbd2cSJim Jagielski 
119*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_doubleToUString that appends to an
120*b1cdbd2cSJim Jagielski     rtl::OUStringBuffer, with no grouping.
121*b1cdbd2cSJim Jagielski  */
doubleToUStringBuffer(rtl::OUStringBuffer & rBuffer,double fValue,rtl_math_StringFormat eFormat,sal_Int32 nDecPlaces,sal_Unicode cDecSeparator,bool bEraseTrailingDecZeros=false)122*b1cdbd2cSJim Jagielski inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
123*b1cdbd2cSJim Jagielski                                    rtl_math_StringFormat eFormat,
124*b1cdbd2cSJim Jagielski                                    sal_Int32 nDecPlaces,
125*b1cdbd2cSJim Jagielski                                    sal_Unicode cDecSeparator,
126*b1cdbd2cSJim Jagielski                                    bool bEraseTrailingDecZeros = false)
127*b1cdbd2cSJim Jagielski {
128*b1cdbd2cSJim Jagielski     rtl_uString ** pData;
129*b1cdbd2cSJim Jagielski     sal_Int32 * pCapacity;
130*b1cdbd2cSJim Jagielski     rBuffer.accessInternals( &pData, &pCapacity );
131*b1cdbd2cSJim Jagielski     rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
132*b1cdbd2cSJim Jagielski                               eFormat, nDecPlaces, cDecSeparator, 0, 0,
133*b1cdbd2cSJim Jagielski                               bEraseTrailingDecZeros);
134*b1cdbd2cSJim Jagielski }
135*b1cdbd2cSJim Jagielski 
136*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_stringToDouble.
137*b1cdbd2cSJim Jagielski  */
stringToDouble(rtl::OString const & rString,sal_Char cDecSeparator,sal_Char cGroupSeparator,rtl_math_ConversionStatus * pStatus,sal_Int32 * pParsedEnd)138*b1cdbd2cSJim Jagielski inline double stringToDouble(rtl::OString const & rString,
139*b1cdbd2cSJim Jagielski                              sal_Char cDecSeparator, sal_Char cGroupSeparator,
140*b1cdbd2cSJim Jagielski                              rtl_math_ConversionStatus * pStatus,
141*b1cdbd2cSJim Jagielski                              sal_Int32 * pParsedEnd)
142*b1cdbd2cSJim Jagielski {
143*b1cdbd2cSJim Jagielski     sal_Char const * pBegin = rString.getStr();
144*b1cdbd2cSJim Jagielski     sal_Char const * pEnd;
145*b1cdbd2cSJim Jagielski     double fResult = rtl_math_stringToDouble(pBegin,
146*b1cdbd2cSJim Jagielski                                              pBegin + rString.getLength(),
147*b1cdbd2cSJim Jagielski                                              cDecSeparator, cGroupSeparator,
148*b1cdbd2cSJim Jagielski                                              pStatus, &pEnd);
149*b1cdbd2cSJim Jagielski     if (pParsedEnd != 0)
150*b1cdbd2cSJim Jagielski         *pParsedEnd = (sal_Int32)(pEnd - pBegin);
151*b1cdbd2cSJim Jagielski     return fResult;
152*b1cdbd2cSJim Jagielski }
153*b1cdbd2cSJim Jagielski 
154*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_uStringToDouble.
155*b1cdbd2cSJim Jagielski  */
stringToDouble(rtl::OUString const & rString,sal_Unicode cDecSeparator,sal_Unicode cGroupSeparator,rtl_math_ConversionStatus * pStatus,sal_Int32 * pParsedEnd)156*b1cdbd2cSJim Jagielski inline double stringToDouble(rtl::OUString const & rString,
157*b1cdbd2cSJim Jagielski                              sal_Unicode cDecSeparator,
158*b1cdbd2cSJim Jagielski                              sal_Unicode cGroupSeparator,
159*b1cdbd2cSJim Jagielski                              rtl_math_ConversionStatus * pStatus,
160*b1cdbd2cSJim Jagielski                              sal_Int32 * pParsedEnd)
161*b1cdbd2cSJim Jagielski {
162*b1cdbd2cSJim Jagielski     sal_Unicode const * pBegin = rString.getStr();
163*b1cdbd2cSJim Jagielski     sal_Unicode const * pEnd;
164*b1cdbd2cSJim Jagielski     double fResult = rtl_math_uStringToDouble(pBegin,
165*b1cdbd2cSJim Jagielski                                               pBegin + rString.getLength(),
166*b1cdbd2cSJim Jagielski                                               cDecSeparator, cGroupSeparator,
167*b1cdbd2cSJim Jagielski                                               pStatus, &pEnd);
168*b1cdbd2cSJim Jagielski     if (pParsedEnd != 0)
169*b1cdbd2cSJim Jagielski         *pParsedEnd = (sal_Int32)(pEnd - pBegin);
170*b1cdbd2cSJim Jagielski     return fResult;
171*b1cdbd2cSJim Jagielski }
172*b1cdbd2cSJim Jagielski 
173*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_round.
174*b1cdbd2cSJim Jagielski  */
round(double fValue,int nDecPlaces=0,rtl_math_RoundingMode eMode=rtl_math_RoundingMode_Corrected)175*b1cdbd2cSJim Jagielski inline double round(
176*b1cdbd2cSJim Jagielski     double fValue, int nDecPlaces = 0,
177*b1cdbd2cSJim Jagielski     rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected)
178*b1cdbd2cSJim Jagielski {
179*b1cdbd2cSJim Jagielski     return rtl_math_round(fValue, nDecPlaces, eMode);
180*b1cdbd2cSJim Jagielski }
181*b1cdbd2cSJim Jagielski 
182*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_pow10Exp.
183*b1cdbd2cSJim Jagielski  */
pow10Exp(double fValue,int nExp)184*b1cdbd2cSJim Jagielski inline double pow10Exp(double fValue, int nExp)
185*b1cdbd2cSJim Jagielski {
186*b1cdbd2cSJim Jagielski     return rtl_math_pow10Exp(fValue, nExp);
187*b1cdbd2cSJim Jagielski }
188*b1cdbd2cSJim Jagielski 
189*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_approxValue.
190*b1cdbd2cSJim Jagielski  */
approxValue(double fValue)191*b1cdbd2cSJim Jagielski inline double approxValue(double fValue)
192*b1cdbd2cSJim Jagielski {
193*b1cdbd2cSJim Jagielski     return rtl_math_approxValue(fValue);
194*b1cdbd2cSJim Jagielski }
195*b1cdbd2cSJim Jagielski 
196*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_expm1.
197*b1cdbd2cSJim Jagielski  */
expm1(double fValue)198*b1cdbd2cSJim Jagielski inline double expm1(double fValue)
199*b1cdbd2cSJim Jagielski {
200*b1cdbd2cSJim Jagielski     return rtl_math_expm1(fValue);
201*b1cdbd2cSJim Jagielski }
202*b1cdbd2cSJim Jagielski 
203*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_log1p.
204*b1cdbd2cSJim Jagielski  */
log1p(double fValue)205*b1cdbd2cSJim Jagielski inline double log1p(double fValue)
206*b1cdbd2cSJim Jagielski {
207*b1cdbd2cSJim Jagielski     return rtl_math_log1p(fValue);
208*b1cdbd2cSJim Jagielski }
209*b1cdbd2cSJim Jagielski 
210*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_atanh.
211*b1cdbd2cSJim Jagielski  */
atanh(double fValue)212*b1cdbd2cSJim Jagielski inline double atanh(double fValue)
213*b1cdbd2cSJim Jagielski {
214*b1cdbd2cSJim Jagielski     return rtl_math_atanh(fValue);
215*b1cdbd2cSJim Jagielski }
216*b1cdbd2cSJim Jagielski 
217*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_erf.
218*b1cdbd2cSJim Jagielski  */
erf(double fValue)219*b1cdbd2cSJim Jagielski inline double erf(double fValue)
220*b1cdbd2cSJim Jagielski {
221*b1cdbd2cSJim Jagielski     return rtl_math_erf(fValue);
222*b1cdbd2cSJim Jagielski }
223*b1cdbd2cSJim Jagielski 
224*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_erfc.
225*b1cdbd2cSJim Jagielski  */
erfc(double fValue)226*b1cdbd2cSJim Jagielski inline double erfc(double fValue)
227*b1cdbd2cSJim Jagielski {
228*b1cdbd2cSJim Jagielski     return rtl_math_erfc(fValue);
229*b1cdbd2cSJim Jagielski }
230*b1cdbd2cSJim Jagielski 
231*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_asinh.
232*b1cdbd2cSJim Jagielski  */
asinh(double fValue)233*b1cdbd2cSJim Jagielski inline double asinh(double fValue)
234*b1cdbd2cSJim Jagielski {
235*b1cdbd2cSJim Jagielski     return rtl_math_asinh(fValue);
236*b1cdbd2cSJim Jagielski }
237*b1cdbd2cSJim Jagielski 
238*b1cdbd2cSJim Jagielski /** A wrapper around rtl_math_acosh.
239*b1cdbd2cSJim Jagielski  */
acosh(double fValue)240*b1cdbd2cSJim Jagielski inline double acosh(double fValue)
241*b1cdbd2cSJim Jagielski {
242*b1cdbd2cSJim Jagielski     return rtl_math_acosh(fValue);
243*b1cdbd2cSJim Jagielski }
244*b1cdbd2cSJim Jagielski 
245*b1cdbd2cSJim Jagielski 
246*b1cdbd2cSJim Jagielski /** Test equality of two values with an accuracy of the magnitude of the
247*b1cdbd2cSJim Jagielski     given values scaled by 2^-48 (4 bits roundoff stripped).
248*b1cdbd2cSJim Jagielski 
249*b1cdbd2cSJim Jagielski     @ATTENTION
250*b1cdbd2cSJim Jagielski     approxEqual( value!=0.0, 0.0 ) _never_ yields true.
251*b1cdbd2cSJim Jagielski  */
approxEqual(double a,double b)252*b1cdbd2cSJim Jagielski inline bool approxEqual(double a, double b)
253*b1cdbd2cSJim Jagielski {
254*b1cdbd2cSJim Jagielski 	if ( a == b )
255*b1cdbd2cSJim Jagielski 		return true;
256*b1cdbd2cSJim Jagielski 	double x = a - b;
257*b1cdbd2cSJim Jagielski 	return (x < 0.0 ? -x : x)
258*b1cdbd2cSJim Jagielski         < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
259*b1cdbd2cSJim Jagielski }
260*b1cdbd2cSJim Jagielski 
261*b1cdbd2cSJim Jagielski /** Add two values.
262*b1cdbd2cSJim Jagielski 
263*b1cdbd2cSJim Jagielski     If signs differ and the absolute values are equal according to approxEqual()
264*b1cdbd2cSJim Jagielski     the method returns 0.0 instead of calculating the sum.
265*b1cdbd2cSJim Jagielski 
266*b1cdbd2cSJim Jagielski     If you wanted to sum up multiple values it would be convenient not to call
267*b1cdbd2cSJim Jagielski     approxAdd() for each value but instead remember the first value not equal to
268*b1cdbd2cSJim Jagielski     0.0, add all other values using normal + operator, and with the result and
269*b1cdbd2cSJim Jagielski     the remembered value call approxAdd().
270*b1cdbd2cSJim Jagielski  */
approxAdd(double a,double b)271*b1cdbd2cSJim Jagielski inline double approxAdd(double a, double b)
272*b1cdbd2cSJim Jagielski {
273*b1cdbd2cSJim Jagielski 	if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0))
274*b1cdbd2cSJim Jagielski          && approxEqual( a, -b ) )
275*b1cdbd2cSJim Jagielski 		return 0.0;
276*b1cdbd2cSJim Jagielski 	return a + b;
277*b1cdbd2cSJim Jagielski }
278*b1cdbd2cSJim Jagielski 
279*b1cdbd2cSJim Jagielski /** Substract two values (a-b).
280*b1cdbd2cSJim Jagielski 
281*b1cdbd2cSJim Jagielski     If signs are identical and the values are equal according to approxEqual()
282*b1cdbd2cSJim Jagielski     the method returns 0.0 instead of calculating the substraction.
283*b1cdbd2cSJim Jagielski  */
approxSub(double a,double b)284*b1cdbd2cSJim Jagielski inline double approxSub(double a, double b)
285*b1cdbd2cSJim Jagielski {
286*b1cdbd2cSJim Jagielski 	if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) )
287*b1cdbd2cSJim Jagielski 		return 0.0;
288*b1cdbd2cSJim Jagielski 	return a - b;
289*b1cdbd2cSJim Jagielski }
290*b1cdbd2cSJim Jagielski 
291*b1cdbd2cSJim Jagielski /** floor() method taking approxValue() into account.
292*b1cdbd2cSJim Jagielski 
293*b1cdbd2cSJim Jagielski     Use for expected integer values being calculated by double functions.
294*b1cdbd2cSJim Jagielski  */
approxFloor(double a)295*b1cdbd2cSJim Jagielski inline double approxFloor(double a)
296*b1cdbd2cSJim Jagielski {
297*b1cdbd2cSJim Jagielski     return floor( approxValue( a ));
298*b1cdbd2cSJim Jagielski }
299*b1cdbd2cSJim Jagielski 
300*b1cdbd2cSJim Jagielski /** ceil() method taking approxValue() into account.
301*b1cdbd2cSJim Jagielski 
302*b1cdbd2cSJim Jagielski     Use for expected integer values being calculated by double functions.
303*b1cdbd2cSJim Jagielski  */
approxCeil(double a)304*b1cdbd2cSJim Jagielski inline double approxCeil(double a)
305*b1cdbd2cSJim Jagielski {
306*b1cdbd2cSJim Jagielski     return ceil( approxValue( a ));
307*b1cdbd2cSJim Jagielski }
308*b1cdbd2cSJim Jagielski 
309*b1cdbd2cSJim Jagielski /** Tests whether a value is neither INF nor NAN.
310*b1cdbd2cSJim Jagielski  */
isFinite(double d)311*b1cdbd2cSJim Jagielski inline bool isFinite(double d)
312*b1cdbd2cSJim Jagielski {
313*b1cdbd2cSJim Jagielski     return SAL_MATH_FINITE(d) != 0;
314*b1cdbd2cSJim Jagielski }
315*b1cdbd2cSJim Jagielski 
316*b1cdbd2cSJim Jagielski /** If a value represents +INF or -INF.
317*b1cdbd2cSJim Jagielski 
318*b1cdbd2cSJim Jagielski     The sign bit may be queried with isSignBitSet().
319*b1cdbd2cSJim Jagielski 
320*b1cdbd2cSJim Jagielski     If isFinite(d)==false and isInf(d)==false then NAN.
321*b1cdbd2cSJim Jagielski  */
isInf(double d)322*b1cdbd2cSJim Jagielski inline bool isInf(double d)
323*b1cdbd2cSJim Jagielski {
324*b1cdbd2cSJim Jagielski 	// exponent==0x7ff fraction==0
325*b1cdbd2cSJim Jagielski 	return (SAL_MATH_FINITE(d) == 0) &&
326*b1cdbd2cSJim Jagielski         (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0)
327*b1cdbd2cSJim Jagielski         && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
328*b1cdbd2cSJim Jagielski             == 0);
329*b1cdbd2cSJim Jagielski }
330*b1cdbd2cSJim Jagielski 
331*b1cdbd2cSJim Jagielski /** Test on any QNAN or SNAN.
332*b1cdbd2cSJim Jagielski  */
isNan(double d)333*b1cdbd2cSJim Jagielski inline bool isNan(double d)
334*b1cdbd2cSJim Jagielski {
335*b1cdbd2cSJim Jagielski 	// exponent==0x7ff fraction!=0
336*b1cdbd2cSJim Jagielski 	return (SAL_MATH_FINITE(d) == 0) && (
337*b1cdbd2cSJim Jagielski         (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0)
338*b1cdbd2cSJim Jagielski         || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
339*b1cdbd2cSJim Jagielski             != 0) );
340*b1cdbd2cSJim Jagielski }
341*b1cdbd2cSJim Jagielski 
342*b1cdbd2cSJim Jagielski /** If the sign bit is set.
343*b1cdbd2cSJim Jagielski  */
isSignBitSet(double d)344*b1cdbd2cSJim Jagielski inline bool isSignBitSet(double d)
345*b1cdbd2cSJim Jagielski {
346*b1cdbd2cSJim Jagielski     return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0;
347*b1cdbd2cSJim Jagielski }
348*b1cdbd2cSJim Jagielski 
349*b1cdbd2cSJim Jagielski /** Set to +INF if bNegative==false or -INF if bNegative==true.
350*b1cdbd2cSJim Jagielski  */
setInf(double * pd,bool bNegative)351*b1cdbd2cSJim Jagielski inline void setInf(double * pd, bool bNegative)
352*b1cdbd2cSJim Jagielski {
353*b1cdbd2cSJim Jagielski     union
354*b1cdbd2cSJim Jagielski     {
355*b1cdbd2cSJim Jagielski         double sd;
356*b1cdbd2cSJim Jagielski         sal_math_Double md;
357*b1cdbd2cSJim Jagielski     };
358*b1cdbd2cSJim Jagielski     md.w32_parts.msw = bNegative ? 0xFFF00000 : 0x7FF00000;
359*b1cdbd2cSJim Jagielski     md.w32_parts.lsw = 0;
360*b1cdbd2cSJim Jagielski     *pd = sd;
361*b1cdbd2cSJim Jagielski }
362*b1cdbd2cSJim Jagielski 
363*b1cdbd2cSJim Jagielski /** Set a QNAN.
364*b1cdbd2cSJim Jagielski  */
setNan(double * pd)365*b1cdbd2cSJim Jagielski inline void setNan(double * pd)
366*b1cdbd2cSJim Jagielski {
367*b1cdbd2cSJim Jagielski     union
368*b1cdbd2cSJim Jagielski     {
369*b1cdbd2cSJim Jagielski         double sd;
370*b1cdbd2cSJim Jagielski         sal_math_Double md;
371*b1cdbd2cSJim Jagielski     };
372*b1cdbd2cSJim Jagielski     md.w32_parts.msw = 0x7FFFFFFF;
373*b1cdbd2cSJim Jagielski     md.w32_parts.lsw = 0xFFFFFFFF;
374*b1cdbd2cSJim Jagielski     *pd = sd;
375*b1cdbd2cSJim Jagielski }
376*b1cdbd2cSJim Jagielski 
377*b1cdbd2cSJim Jagielski /** If a value is a valid argument for sin(), cos(), tan().
378*b1cdbd2cSJim Jagielski 
379*b1cdbd2cSJim Jagielski     IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
380*b1cdbd2cSJim Jagielski     radian must be supported by trigonometric functions.  Unfortunately, at
381*b1cdbd2cSJim Jagielski     least on x86 architectures, the FPU doesn't generate an error pattern for
382*b1cdbd2cSJim Jagielski     values >2^64 but produces erroneous results instead and sets only the
383*b1cdbd2cSJim Jagielski     "invalid operation" (IM) flag in the status word :-(  Thus the application
384*b1cdbd2cSJim Jagielski     has to handle it itself.
385*b1cdbd2cSJim Jagielski  */
isValidArcArg(double d)386*b1cdbd2cSJim Jagielski inline bool isValidArcArg(double d)
387*b1cdbd2cSJim Jagielski {
388*b1cdbd2cSJim Jagielski     return fabs(d)
389*b1cdbd2cSJim Jagielski         <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
390*b1cdbd2cSJim Jagielski             * static_cast< double >(static_cast< unsigned long >(0x80000000))
391*b1cdbd2cSJim Jagielski             * 2);
392*b1cdbd2cSJim Jagielski }
393*b1cdbd2cSJim Jagielski 
394*b1cdbd2cSJim Jagielski /** Safe sin(), returns NAN if not valid.
395*b1cdbd2cSJim Jagielski  */
sin(double d)396*b1cdbd2cSJim Jagielski inline double sin(double d)
397*b1cdbd2cSJim Jagielski {
398*b1cdbd2cSJim Jagielski     if ( isValidArcArg( d ) )
399*b1cdbd2cSJim Jagielski         return ::sin( d );
400*b1cdbd2cSJim Jagielski     setNan( &d );
401*b1cdbd2cSJim Jagielski     return d;
402*b1cdbd2cSJim Jagielski }
403*b1cdbd2cSJim Jagielski 
404*b1cdbd2cSJim Jagielski /** Safe cos(), returns NAN if not valid.
405*b1cdbd2cSJim Jagielski  */
cos(double d)406*b1cdbd2cSJim Jagielski inline double cos(double d)
407*b1cdbd2cSJim Jagielski {
408*b1cdbd2cSJim Jagielski     if ( isValidArcArg( d ) )
409*b1cdbd2cSJim Jagielski         return ::cos( d );
410*b1cdbd2cSJim Jagielski     setNan( &d );
411*b1cdbd2cSJim Jagielski     return d;
412*b1cdbd2cSJim Jagielski }
413*b1cdbd2cSJim Jagielski 
414*b1cdbd2cSJim Jagielski /** Safe tan(), returns NAN if not valid.
415*b1cdbd2cSJim Jagielski  */
tan(double d)416*b1cdbd2cSJim Jagielski inline double tan(double d)
417*b1cdbd2cSJim Jagielski {
418*b1cdbd2cSJim Jagielski     if ( isValidArcArg( d ) )
419*b1cdbd2cSJim Jagielski         return ::tan( d );
420*b1cdbd2cSJim Jagielski     setNan( &d );
421*b1cdbd2cSJim Jagielski     return d;
422*b1cdbd2cSJim Jagielski }
423*b1cdbd2cSJim Jagielski 
424*b1cdbd2cSJim Jagielski }
425*b1cdbd2cSJim Jagielski 
426*b1cdbd2cSJim Jagielski }
427*b1cdbd2cSJim Jagielski 
428*b1cdbd2cSJim Jagielski #endif // INCLUDED_RTL_MATH_HXX
429