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