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