update dev300-m58
[ooovba.git] / sal / inc / rtl / math.hxx
blob4223415cdff96ef49e78c990f75188762c6dca16
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: math.hxx,v $
10 * $Revision: 1.8 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #if !defined INCLUDED_RTL_MATH_HXX
32 #define INCLUDED_RTL_MATH_HXX
34 #include "rtl/math.h"
35 #include "rtl/string.hxx"
36 #include "rtl/ustring.hxx"
37 #include "rtl/ustrbuf.hxx"
38 #include "sal/mathconf.h"
39 #include "sal/types.h"
41 #include <math.h>
43 namespace rtl {
45 namespace math {
47 /** A wrapper around rtl_math_doubleToString.
49 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
50 sal_Int32 nDecPlaces,
51 sal_Char cDecSeparator,
52 sal_Int32 const * pGroups,
53 sal_Char cGroupSeparator,
54 bool bEraseTrailingDecZeros = false)
56 rtl::OString aResult;
57 rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
58 cDecSeparator, pGroups, cGroupSeparator,
59 bEraseTrailingDecZeros);
60 return aResult;
63 /** A wrapper around rtl_math_doubleToString, with no grouping.
65 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
66 sal_Int32 nDecPlaces,
67 sal_Char cDecSeparator,
68 bool bEraseTrailingDecZeros = false)
70 rtl::OString aResult;
71 rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
72 cDecSeparator, 0, 0, bEraseTrailingDecZeros);
73 return aResult;
76 /** A wrapper around rtl_math_doubleToUString.
78 inline rtl::OUString doubleToUString(double fValue,
79 rtl_math_StringFormat eFormat,
80 sal_Int32 nDecPlaces,
81 sal_Unicode cDecSeparator,
82 sal_Int32 const * pGroups,
83 sal_Unicode cGroupSeparator,
84 bool bEraseTrailingDecZeros = false)
86 rtl::OUString aResult;
87 rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
88 cDecSeparator, pGroups, cGroupSeparator,
89 bEraseTrailingDecZeros);
90 return aResult;
93 /** A wrapper around rtl_math_doubleToUString, with no grouping.
95 inline rtl::OUString doubleToUString(double fValue,
96 rtl_math_StringFormat eFormat,
97 sal_Int32 nDecPlaces,
98 sal_Unicode cDecSeparator,
99 bool bEraseTrailingDecZeros = false)
101 rtl::OUString aResult;
102 rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
103 cDecSeparator, 0, 0, bEraseTrailingDecZeros);
104 return aResult;
107 /** A wrapper around rtl_math_doubleToUString that appends to an
108 rtl::OUStringBuffer.
110 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
111 rtl_math_StringFormat eFormat,
112 sal_Int32 nDecPlaces,
113 sal_Unicode cDecSeparator,
114 sal_Int32 const * pGroups,
115 sal_Unicode cGroupSeparator,
116 bool bEraseTrailingDecZeros = false)
118 rtl_uString ** pData;
119 sal_Int32 * pCapacity;
120 rBuffer.accessInternals( &pData, &pCapacity );
121 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
122 eFormat, nDecPlaces, cDecSeparator, pGroups,
123 cGroupSeparator, bEraseTrailingDecZeros);
126 /** A wrapper around rtl_math_doubleToUString that appends to an
127 rtl::OUStringBuffer, with no grouping.
129 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
130 rtl_math_StringFormat eFormat,
131 sal_Int32 nDecPlaces,
132 sal_Unicode cDecSeparator,
133 bool bEraseTrailingDecZeros = false)
135 rtl_uString ** pData;
136 sal_Int32 * pCapacity;
137 rBuffer.accessInternals( &pData, &pCapacity );
138 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
139 eFormat, nDecPlaces, cDecSeparator, 0, 0,
140 bEraseTrailingDecZeros);
143 /** A wrapper around rtl_math_stringToDouble.
145 inline double stringToDouble(rtl::OString const & rString,
146 sal_Char cDecSeparator, sal_Char cGroupSeparator,
147 rtl_math_ConversionStatus * pStatus,
148 sal_Int32 * pParsedEnd)
150 sal_Char const * pBegin = rString.getStr();
151 sal_Char const * pEnd;
152 double fResult = rtl_math_stringToDouble(pBegin,
153 pBegin + rString.getLength(),
154 cDecSeparator, cGroupSeparator,
155 pStatus, &pEnd);
156 if (pParsedEnd != 0)
157 *pParsedEnd = (sal_Int32)(pEnd - pBegin);
158 return fResult;
161 /** A wrapper around rtl_math_uStringToDouble.
163 inline double stringToDouble(rtl::OUString const & rString,
164 sal_Unicode cDecSeparator,
165 sal_Unicode cGroupSeparator,
166 rtl_math_ConversionStatus * pStatus,
167 sal_Int32 * pParsedEnd)
169 sal_Unicode const * pBegin = rString.getStr();
170 sal_Unicode const * pEnd;
171 double fResult = rtl_math_uStringToDouble(pBegin,
172 pBegin + rString.getLength(),
173 cDecSeparator, cGroupSeparator,
174 pStatus, &pEnd);
175 if (pParsedEnd != 0)
176 *pParsedEnd = (sal_Int32)(pEnd - pBegin);
177 return fResult;
180 /** A wrapper around rtl_math_round.
182 inline double round(
183 double fValue, int nDecPlaces = 0,
184 rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected)
186 return rtl_math_round(fValue, nDecPlaces, eMode);
189 /** A wrapper around rtl_math_pow10Exp.
191 inline double pow10Exp(double fValue, int nExp)
193 return rtl_math_pow10Exp(fValue, nExp);
196 /** A wrapper around rtl_math_approxValue.
198 inline double approxValue(double fValue)
200 return rtl_math_approxValue(fValue);
203 /** A wrapper around rtl_math_expm1.
205 inline double expm1(double fValue)
207 return rtl_math_expm1(fValue);
210 /** A wrapper around rtl_math_log1p.
212 inline double log1p(double fValue)
214 return rtl_math_log1p(fValue);
217 /** A wrapper around rtl_math_atanh.
219 inline double atanh(double fValue)
221 return rtl_math_atanh(fValue);
224 /** Test equality of two values with an accuracy of the magnitude of the
225 given values scaled by 2^-48 (4 bits roundoff stripped).
227 @ATTENTION
228 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
230 inline bool approxEqual(double a, double b)
232 if ( a == b )
233 return true;
234 double x = a - b;
235 return (x < 0.0 ? -x : x)
236 < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
239 /** Add two values.
241 If signs differ and the absolute values are equal according to approxEqual()
242 the method returns 0.0 instead of calculating the sum.
244 If you wanted to sum up multiple values it would be convenient not to call
245 approxAdd() for each value but instead remember the first value not equal to
246 0.0, add all other values using normal + operator, and with the result and
247 the remembered value call approxAdd().
249 inline double approxAdd(double a, double b)
251 if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0))
252 && approxEqual( a, -b ) )
253 return 0.0;
254 return a + b;
257 /** Substract two values (a-b).
259 If signs are identical and the values are equal according to approxEqual()
260 the method returns 0.0 instead of calculating the substraction.
262 inline double approxSub(double a, double b)
264 if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) )
265 return 0.0;
266 return a - b;
269 /** floor() method taking approxValue() into account.
271 Use for expected integer values being calculated by double functions.
273 inline double approxFloor(double a)
275 return floor( approxValue( a ));
278 /** ceil() method taking approxValue() into account.
280 Use for expected integer values being calculated by double functions.
282 inline double approxCeil(double a)
284 return ceil( approxValue( a ));
287 /** Tests whether a value is neither INF nor NAN.
289 inline bool isFinite(double d)
291 return SAL_MATH_FINITE(d) != 0;
294 /** If a value represents +INF or -INF.
296 The sign bit may be queried with isSignBitSet().
298 If isFinite(d)==false and isInf(d)==false then NAN.
300 inline bool isInf(double d)
302 // exponent==0x7ff fraction==0
303 return (SAL_MATH_FINITE(d) == 0) &&
304 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0)
305 && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
306 == 0);
309 /** Test on any QNAN or SNAN.
311 inline bool isNan(double d)
313 // exponent==0x7ff fraction!=0
314 return (SAL_MATH_FINITE(d) == 0) && (
315 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0)
316 || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
317 != 0) );
320 /** If the sign bit is set.
322 inline bool isSignBitSet(double d)
324 return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0;
327 /** Set to +INF if bNegative==false or -INF if bNegative==true.
329 inline void setInf(double * pd, bool bNegative)
331 reinterpret_cast< sal_math_Double * >(pd)->w32_parts.msw
332 = bNegative ? 0xFFF00000 : 0x7FF00000;
333 reinterpret_cast< sal_math_Double * >(pd)->w32_parts.lsw = 0;
336 /** Set a QNAN.
338 inline void setNan(double * pd)
340 reinterpret_cast< sal_math_Double * >(pd)->w32_parts.msw = 0x7FFFFFFF;
341 reinterpret_cast< sal_math_Double * >(pd)->w32_parts.lsw = 0xFFFFFFFF;
344 /** If a value is a valid argument for sin(), cos(), tan().
346 IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
347 radian must be supported by trigonometric functions. Unfortunately, at
348 least on x86 architectures, the FPU doesn't generate an error pattern for
349 values >2^64 but produces erroneous results instead and sets only the
350 "invalid operation" (IM) flag in the status word :-( Thus the application
351 has to handle it itself.
353 inline bool isValidArcArg(double d)
355 return fabs(d)
356 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
357 * static_cast< double >(static_cast< unsigned long >(0x80000000))
358 * 2);
361 /** Safe sin(), returns NAN if not valid.
363 inline double sin(double d)
365 if ( isValidArcArg( d ) )
366 return ::sin( d );
367 setNan( &d );
368 return d;
371 /** Safe cos(), returns NAN if not valid.
373 inline double cos(double d)
375 if ( isValidArcArg( d ) )
376 return ::cos( d );
377 setNan( &d );
378 return d;
381 /** Safe tan(), returns NAN if not valid.
383 inline double tan(double d)
385 if ( isValidArcArg( d ) )
386 return ::tan( d );
387 setNan( &d );
388 return d;
395 #endif // INCLUDED_RTL_MATH_HXX