1565d668cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3565d668cSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4565d668cSAndrew Rist * or more contributor license agreements. See the NOTICE file
5565d668cSAndrew Rist * distributed with this work for additional information
6565d668cSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7565d668cSAndrew Rist * to you under the Apache License, Version 2.0 (the
8565d668cSAndrew Rist * "License"); you may not use this file except in compliance
9565d668cSAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11565d668cSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13565d668cSAndrew Rist * Unless required by applicable law or agreed to in writing,
14565d668cSAndrew Rist * software distributed under the License is distributed on an
15565d668cSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16565d668cSAndrew Rist * KIND, either express or implied. See the License for the
17565d668cSAndrew Rist * specific language governing permissions and limitations
18565d668cSAndrew Rist * under the License.
19cdf0e10cSrcweir *
20565d668cSAndrew Rist *************************************************************/
21565d668cSAndrew Rist
22565d668cSAndrew 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
189*cda7f8b3SPedro Giffuni /** A wrapper around rtl_math_powr.
190*cda7f8b3SPedro Giffuni */
powr(double fValue,double fExp)191*cda7f8b3SPedro Giffuni inline double powr(double fValue, double fExp)
192*cda7f8b3SPedro Giffuni {
193*cda7f8b3SPedro Giffuni return rtl_math_powr(fValue, fExp);
194*cda7f8b3SPedro Giffuni }
195*cda7f8b3SPedro Giffuni
196cdf0e10cSrcweir /** A wrapper around rtl_math_approxValue.
197cdf0e10cSrcweir */
approxValue(double fValue)198cdf0e10cSrcweir inline double approxValue(double fValue)
199cdf0e10cSrcweir {
200cdf0e10cSrcweir return rtl_math_approxValue(fValue);
201cdf0e10cSrcweir }
202cdf0e10cSrcweir
203cdf0e10cSrcweir /** A wrapper around rtl_math_expm1.
204cdf0e10cSrcweir */
expm1(double fValue)205cdf0e10cSrcweir inline double expm1(double fValue)
206cdf0e10cSrcweir {
207cdf0e10cSrcweir return rtl_math_expm1(fValue);
208cdf0e10cSrcweir }
209cdf0e10cSrcweir
210cdf0e10cSrcweir /** A wrapper around rtl_math_log1p.
211cdf0e10cSrcweir */
log1p(double fValue)212cdf0e10cSrcweir inline double log1p(double fValue)
213cdf0e10cSrcweir {
214cdf0e10cSrcweir return rtl_math_log1p(fValue);
215cdf0e10cSrcweir }
216cdf0e10cSrcweir
217cdf0e10cSrcweir /** A wrapper around rtl_math_atanh.
218cdf0e10cSrcweir */
atanh(double fValue)219cdf0e10cSrcweir inline double atanh(double fValue)
220cdf0e10cSrcweir {
221cdf0e10cSrcweir return rtl_math_atanh(fValue);
222cdf0e10cSrcweir }
223cdf0e10cSrcweir
224cdf0e10cSrcweir /** A wrapper around rtl_math_erf.
225cdf0e10cSrcweir */
erf(double fValue)226cdf0e10cSrcweir inline double erf(double fValue)
227cdf0e10cSrcweir {
228cdf0e10cSrcweir return rtl_math_erf(fValue);
229cdf0e10cSrcweir }
230cdf0e10cSrcweir
231cdf0e10cSrcweir /** A wrapper around rtl_math_erfc.
232cdf0e10cSrcweir */
erfc(double fValue)233cdf0e10cSrcweir inline double erfc(double fValue)
234cdf0e10cSrcweir {
235cdf0e10cSrcweir return rtl_math_erfc(fValue);
236cdf0e10cSrcweir }
237cdf0e10cSrcweir
238cdf0e10cSrcweir /** A wrapper around rtl_math_asinh.
239cdf0e10cSrcweir */
asinh(double fValue)240cdf0e10cSrcweir inline double asinh(double fValue)
241cdf0e10cSrcweir {
242cdf0e10cSrcweir return rtl_math_asinh(fValue);
243cdf0e10cSrcweir }
244cdf0e10cSrcweir
245cdf0e10cSrcweir /** A wrapper around rtl_math_acosh.
246cdf0e10cSrcweir */
acosh(double fValue)247cdf0e10cSrcweir inline double acosh(double fValue)
248cdf0e10cSrcweir {
249cdf0e10cSrcweir return rtl_math_acosh(fValue);
250cdf0e10cSrcweir }
251cdf0e10cSrcweir
252cdf0e10cSrcweir
253cdf0e10cSrcweir /** Test equality of two values with an accuracy of the magnitude of the
254cdf0e10cSrcweir given values scaled by 2^-48 (4 bits roundoff stripped).
255cdf0e10cSrcweir
256cdf0e10cSrcweir @ATTENTION
257cdf0e10cSrcweir approxEqual( value!=0.0, 0.0 ) _never_ yields true.
258cdf0e10cSrcweir */
approxEqual(double a,double b)259cdf0e10cSrcweir inline bool approxEqual(double a, double b)
260cdf0e10cSrcweir {
261cdf0e10cSrcweir if ( a == b )
262cdf0e10cSrcweir return true;
263cdf0e10cSrcweir double x = a - b;
264cdf0e10cSrcweir return (x < 0.0 ? -x : x)
265cdf0e10cSrcweir < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
266cdf0e10cSrcweir }
267cdf0e10cSrcweir
268cdf0e10cSrcweir /** Add two values.
269cdf0e10cSrcweir
270cdf0e10cSrcweir If signs differ and the absolute values are equal according to approxEqual()
271cdf0e10cSrcweir the method returns 0.0 instead of calculating the sum.
272cdf0e10cSrcweir
273cdf0e10cSrcweir If you wanted to sum up multiple values it would be convenient not to call
274cdf0e10cSrcweir approxAdd() for each value but instead remember the first value not equal to
275cdf0e10cSrcweir 0.0, add all other values using normal + operator, and with the result and
276cdf0e10cSrcweir the remembered value call approxAdd().
277cdf0e10cSrcweir */
approxAdd(double a,double b)278cdf0e10cSrcweir inline double approxAdd(double a, double b)
279cdf0e10cSrcweir {
280cdf0e10cSrcweir if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0))
281cdf0e10cSrcweir && approxEqual( a, -b ) )
282cdf0e10cSrcweir return 0.0;
283cdf0e10cSrcweir return a + b;
284cdf0e10cSrcweir }
285cdf0e10cSrcweir
28686e1cf34SPedro Giffuni /** Subtract two values (a-b).
287cdf0e10cSrcweir
288cdf0e10cSrcweir If signs are identical and the values are equal according to approxEqual()
28986e1cf34SPedro Giffuni the method returns 0.0 instead of calculating the subtraction.
290cdf0e10cSrcweir */
approxSub(double a,double b)291cdf0e10cSrcweir inline double approxSub(double a, double b)
292cdf0e10cSrcweir {
293cdf0e10cSrcweir if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) )
294cdf0e10cSrcweir return 0.0;
295cdf0e10cSrcweir return a - b;
296cdf0e10cSrcweir }
297cdf0e10cSrcweir
298cdf0e10cSrcweir /** floor() method taking approxValue() into account.
299cdf0e10cSrcweir
300cdf0e10cSrcweir Use for expected integer values being calculated by double functions.
301cdf0e10cSrcweir */
approxFloor(double a)302cdf0e10cSrcweir inline double approxFloor(double a)
303cdf0e10cSrcweir {
304cdf0e10cSrcweir return floor( approxValue( a ));
305cdf0e10cSrcweir }
306cdf0e10cSrcweir
307cdf0e10cSrcweir /** ceil() method taking approxValue() into account.
308cdf0e10cSrcweir
309cdf0e10cSrcweir Use for expected integer values being calculated by double functions.
310cdf0e10cSrcweir */
approxCeil(double a)311cdf0e10cSrcweir inline double approxCeil(double a)
312cdf0e10cSrcweir {
313cdf0e10cSrcweir return ceil( approxValue( a ));
314cdf0e10cSrcweir }
315cdf0e10cSrcweir
316cdf0e10cSrcweir /** Tests whether a value is neither INF nor NAN.
317cdf0e10cSrcweir */
isFinite(double d)318cdf0e10cSrcweir inline bool isFinite(double d)
319cdf0e10cSrcweir {
320cdf0e10cSrcweir return SAL_MATH_FINITE(d) != 0;
321cdf0e10cSrcweir }
322cdf0e10cSrcweir
323cdf0e10cSrcweir /** If a value represents +INF or -INF.
324cdf0e10cSrcweir
325cdf0e10cSrcweir The sign bit may be queried with isSignBitSet().
326cdf0e10cSrcweir
327cdf0e10cSrcweir If isFinite(d)==false and isInf(d)==false then NAN.
328cdf0e10cSrcweir */
isInf(double d)329cdf0e10cSrcweir inline bool isInf(double d)
330cdf0e10cSrcweir {
331cdf0e10cSrcweir // exponent==0x7ff fraction==0
332cdf0e10cSrcweir return (SAL_MATH_FINITE(d) == 0) &&
333cdf0e10cSrcweir (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0)
334cdf0e10cSrcweir && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
335cdf0e10cSrcweir == 0);
336cdf0e10cSrcweir }
337cdf0e10cSrcweir
338cdf0e10cSrcweir /** Test on any QNAN or SNAN.
339cdf0e10cSrcweir */
isNan(double d)340cdf0e10cSrcweir inline bool isNan(double d)
341cdf0e10cSrcweir {
342cdf0e10cSrcweir // exponent==0x7ff fraction!=0
343cdf0e10cSrcweir return (SAL_MATH_FINITE(d) == 0) && (
344cdf0e10cSrcweir (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0)
345cdf0e10cSrcweir || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
346cdf0e10cSrcweir != 0) );
347cdf0e10cSrcweir }
348cdf0e10cSrcweir
349cdf0e10cSrcweir /** If the sign bit is set.
350cdf0e10cSrcweir */
isSignBitSet(double d)351cdf0e10cSrcweir inline bool isSignBitSet(double d)
352cdf0e10cSrcweir {
353cdf0e10cSrcweir return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0;
354cdf0e10cSrcweir }
355cdf0e10cSrcweir
356cdf0e10cSrcweir /** Set to +INF if bNegative==false or -INF if bNegative==true.
357cdf0e10cSrcweir */
setInf(double * pd,bool bNegative)358cdf0e10cSrcweir inline void setInf(double * pd, bool bNegative)
359cdf0e10cSrcweir {
360cdf0e10cSrcweir union
361cdf0e10cSrcweir {
362cdf0e10cSrcweir double sd;
363cdf0e10cSrcweir sal_math_Double md;
364cdf0e10cSrcweir };
365cdf0e10cSrcweir md.w32_parts.msw = bNegative ? 0xFFF00000 : 0x7FF00000;
366cdf0e10cSrcweir md.w32_parts.lsw = 0;
367cdf0e10cSrcweir *pd = sd;
368cdf0e10cSrcweir }
369cdf0e10cSrcweir
370cdf0e10cSrcweir /** Set a QNAN.
371cdf0e10cSrcweir */
setNan(double * pd)372cdf0e10cSrcweir inline void setNan(double * pd)
373cdf0e10cSrcweir {
374cdf0e10cSrcweir union
375cdf0e10cSrcweir {
376cdf0e10cSrcweir double sd;
377cdf0e10cSrcweir sal_math_Double md;
378cdf0e10cSrcweir };
379cdf0e10cSrcweir md.w32_parts.msw = 0x7FFFFFFF;
380cdf0e10cSrcweir md.w32_parts.lsw = 0xFFFFFFFF;
381cdf0e10cSrcweir *pd = sd;
382cdf0e10cSrcweir }
383cdf0e10cSrcweir
384cdf0e10cSrcweir /** If a value is a valid argument for sin(), cos(), tan().
385cdf0e10cSrcweir
386cdf0e10cSrcweir IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
387cdf0e10cSrcweir radian must be supported by trigonometric functions. Unfortunately, at
388cdf0e10cSrcweir least on x86 architectures, the FPU doesn't generate an error pattern for
389cdf0e10cSrcweir values >2^64 but produces erroneous results instead and sets only the
390cdf0e10cSrcweir "invalid operation" (IM) flag in the status word :-( Thus the application
391cdf0e10cSrcweir has to handle it itself.
392cdf0e10cSrcweir */
isValidArcArg(double d)393cdf0e10cSrcweir inline bool isValidArcArg(double d)
394cdf0e10cSrcweir {
395cdf0e10cSrcweir return fabs(d)
396cdf0e10cSrcweir <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
397cdf0e10cSrcweir * static_cast< double >(static_cast< unsigned long >(0x80000000))
398cdf0e10cSrcweir * 2);
399cdf0e10cSrcweir }
400cdf0e10cSrcweir
401cdf0e10cSrcweir /** Safe sin(), returns NAN if not valid.
402cdf0e10cSrcweir */
sin(double d)403cdf0e10cSrcweir inline double sin(double d)
404cdf0e10cSrcweir {
405cdf0e10cSrcweir if ( isValidArcArg( d ) )
406cdf0e10cSrcweir return ::sin( d );
407cdf0e10cSrcweir setNan( &d );
408cdf0e10cSrcweir return d;
409cdf0e10cSrcweir }
410cdf0e10cSrcweir
411cdf0e10cSrcweir /** Safe cos(), returns NAN if not valid.
412cdf0e10cSrcweir */
cos(double d)413cdf0e10cSrcweir inline double cos(double d)
414cdf0e10cSrcweir {
415cdf0e10cSrcweir if ( isValidArcArg( d ) )
416cdf0e10cSrcweir return ::cos( d );
417cdf0e10cSrcweir setNan( &d );
418cdf0e10cSrcweir return d;
419cdf0e10cSrcweir }
420cdf0e10cSrcweir
421cdf0e10cSrcweir /** Safe tan(), returns NAN if not valid.
422cdf0e10cSrcweir */
tan(double d)423cdf0e10cSrcweir inline double tan(double d)
424cdf0e10cSrcweir {
425cdf0e10cSrcweir if ( isValidArcArg( d ) )
426cdf0e10cSrcweir return ::tan( d );
427cdf0e10cSrcweir setNan( &d );
428cdf0e10cSrcweir return d;
429cdf0e10cSrcweir }
430cdf0e10cSrcweir
431cdf0e10cSrcweir }
432cdf0e10cSrcweir
433cdf0e10cSrcweir }
434cdf0e10cSrcweir
435cdf0e10cSrcweir #endif // INCLUDED_RTL_MATH_HXX
436