Branch libreoffice-5-0-4
[LibreOffice.git] / include / rtl / math.hxx
blob1b90854bb7ef044f70251e6ea1509fb5f771d799
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_RTL_MATH_HXX
21 #define INCLUDED_RTL_MATH_HXX
23 #include <rtl/math.h>
24 #include <rtl/string.hxx>
25 #include <rtl/ustring.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <sal/mathconf.h>
28 #include <sal/types.h>
30 #include <math.h>
32 namespace rtl {
34 namespace math {
36 /** A wrapper around rtl_math_doubleToString.
38 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
39 sal_Int32 nDecPlaces,
40 sal_Char cDecSeparator,
41 sal_Int32 const * pGroups,
42 sal_Char cGroupSeparator,
43 bool bEraseTrailingDecZeros = false)
45 rtl::OString aResult;
46 rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
47 cDecSeparator, pGroups, cGroupSeparator,
48 bEraseTrailingDecZeros);
49 return aResult;
52 /** A wrapper around rtl_math_doubleToString, with no grouping.
54 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
55 sal_Int32 nDecPlaces,
56 sal_Char cDecSeparator,
57 bool bEraseTrailingDecZeros = false)
59 rtl::OString aResult;
60 rtl_math_doubleToString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
61 cDecSeparator, 0, 0, bEraseTrailingDecZeros);
62 return aResult;
65 /** A wrapper around rtl_math_doubleToUString.
67 inline rtl::OUString doubleToUString(double fValue,
68 rtl_math_StringFormat eFormat,
69 sal_Int32 nDecPlaces,
70 sal_Unicode cDecSeparator,
71 sal_Int32 const * pGroups,
72 sal_Unicode cGroupSeparator,
73 bool bEraseTrailingDecZeros = false)
75 rtl::OUString aResult;
76 rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
77 cDecSeparator, pGroups, cGroupSeparator,
78 bEraseTrailingDecZeros);
79 return aResult;
82 /** A wrapper around rtl_math_doubleToUString, with no grouping.
84 inline rtl::OUString doubleToUString(double fValue,
85 rtl_math_StringFormat eFormat,
86 sal_Int32 nDecPlaces,
87 sal_Unicode cDecSeparator,
88 bool bEraseTrailingDecZeros = false)
90 rtl::OUString aResult;
91 rtl_math_doubleToUString(&aResult.pData, 0, 0, fValue, eFormat, nDecPlaces,
92 cDecSeparator, 0, 0, bEraseTrailingDecZeros);
93 return aResult;
96 /** A wrapper around rtl_math_doubleToUString that appends to an
97 rtl::OUStringBuffer.
99 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
100 rtl_math_StringFormat eFormat,
101 sal_Int32 nDecPlaces,
102 sal_Unicode cDecSeparator,
103 sal_Int32 const * pGroups,
104 sal_Unicode cGroupSeparator,
105 bool bEraseTrailingDecZeros = false)
107 rtl_uString ** pData;
108 sal_Int32 * pCapacity;
109 rBuffer.accessInternals( &pData, &pCapacity );
110 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
111 eFormat, nDecPlaces, cDecSeparator, pGroups,
112 cGroupSeparator, bEraseTrailingDecZeros);
115 /** A wrapper around rtl_math_doubleToUString that appends to an
116 rtl::OUStringBuffer, with no grouping.
118 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
119 rtl_math_StringFormat eFormat,
120 sal_Int32 nDecPlaces,
121 sal_Unicode cDecSeparator,
122 bool bEraseTrailingDecZeros = false)
124 rtl_uString ** pData;
125 sal_Int32 * pCapacity;
126 rBuffer.accessInternals( &pData, &pCapacity );
127 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
128 eFormat, nDecPlaces, cDecSeparator, 0, 0,
129 bEraseTrailingDecZeros);
132 /** A wrapper around rtl_math_stringToDouble.
134 inline double stringToDouble(rtl::OString const & rString,
135 sal_Char cDecSeparator, sal_Char cGroupSeparator,
136 rtl_math_ConversionStatus * pStatus = 0,
137 sal_Int32 * pParsedEnd = 0)
139 sal_Char const * pBegin = rString.getStr();
140 sal_Char const * pEnd;
141 double fResult = rtl_math_stringToDouble(pBegin,
142 pBegin + rString.getLength(),
143 cDecSeparator, cGroupSeparator,
144 pStatus, &pEnd);
145 if (pParsedEnd != 0)
146 *pParsedEnd = (sal_Int32)(pEnd - pBegin);
147 return fResult;
150 /** A wrapper around rtl_math_uStringToDouble.
152 inline double stringToDouble(rtl::OUString const & rString,
153 sal_Unicode cDecSeparator,
154 sal_Unicode cGroupSeparator,
155 rtl_math_ConversionStatus * pStatus = 0,
156 sal_Int32 * pParsedEnd = 0)
158 sal_Unicode const * pBegin = rString.getStr();
159 sal_Unicode const * pEnd;
160 double fResult = rtl_math_uStringToDouble(pBegin,
161 pBegin + rString.getLength(),
162 cDecSeparator, cGroupSeparator,
163 pStatus, &pEnd);
164 if (pParsedEnd != 0)
165 *pParsedEnd = (sal_Int32)(pEnd - pBegin);
166 return fResult;
169 /** A wrapper around rtl_math_round.
171 inline double round(
172 double fValue, int nDecPlaces = 0,
173 rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected)
175 return rtl_math_round(fValue, nDecPlaces, eMode);
178 /** A wrapper around rtl_math_pow10Exp.
180 inline double pow10Exp(double fValue, int nExp)
182 return rtl_math_pow10Exp(fValue, nExp);
185 /** A wrapper around rtl_math_approxValue.
187 inline double approxValue(double fValue)
189 return rtl_math_approxValue(fValue);
192 /** A wrapper around rtl_math_expm1.
194 inline double expm1(double fValue)
196 return rtl_math_expm1(fValue);
199 /** A wrapper around rtl_math_log1p.
201 inline double log1p(double fValue)
203 return rtl_math_log1p(fValue);
206 /** A wrapper around rtl_math_atanh.
208 inline double atanh(double fValue)
210 return rtl_math_atanh(fValue);
213 /** A wrapper around rtl_math_erf.
215 inline double erf(double fValue)
217 return rtl_math_erf(fValue);
220 /** A wrapper around rtl_math_erfc.
222 inline double erfc(double fValue)
224 return rtl_math_erfc(fValue);
227 /** A wrapper around rtl_math_asinh.
229 inline double asinh(double fValue)
231 return rtl_math_asinh(fValue);
234 /** A wrapper around rtl_math_acosh.
236 inline double acosh(double fValue)
238 return rtl_math_acosh(fValue);
242 /** Test equality of two values with an accuracy of the magnitude of the
243 given values scaled by 2^-48 (4 bits roundoff stripped).
245 @attention
246 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
248 inline bool approxEqual(double a, double b)
250 if ( a == b )
251 return true;
252 double x = a - b;
253 return (x < 0.0 ? -x : x)
254 < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
257 /** Test equality of two values with an accuracy defined by nPrec
259 @attention
260 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
262 inline bool approxEqual(double a, double b, sal_Int16 nPrec)
264 if ( a == b )
265 return true;
266 double x = a - b;
267 return (x < 0.0 ? -x : x)
268 < ((a < 0.0 ? -a : a) * (1.0 / (pow(static_cast<double>(2.0), nPrec))));
270 /** Add two values.
272 If signs differ and the absolute values are equal according to approxEqual()
273 the method returns 0.0 instead of calculating the sum.
275 If you wanted to sum up multiple values it would be convenient not to call
276 approxAdd() for each value but instead remember the first value not equal to
277 0.0, add all other values using normal + operator, and with the result and
278 the remembered value call approxAdd().
280 inline double approxAdd(double a, double b)
282 if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0))
283 && approxEqual( a, -b ) )
284 return 0.0;
285 return a + b;
288 /** Subtract two values (a-b).
290 If signs are identical and the values are equal according to approxEqual()
291 the method returns 0.0 instead of calculating the subtraction.
293 inline double approxSub(double a, double b)
295 if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) )
296 return 0.0;
297 return a - b;
300 /** floor() method taking approxValue() into account.
302 Use for expected integer values being calculated by double functions.
304 inline double approxFloor(double a)
306 return floor( approxValue( a ));
309 /** ceil() method taking approxValue() into account.
311 Use for expected integer values being calculated by double functions.
313 inline double approxCeil(double a)
315 return ceil( approxValue( a ));
318 /** Tests whether a value is neither INF nor NAN.
320 inline bool isFinite(double d)
322 return SAL_MATH_FINITE(d);
325 /** If a value represents +INF or -INF.
327 The sign bit may be queried with isSignBitSet().
329 If isFinite(d)==false and isInf(d)==false then NAN.
331 inline bool isInf(double d)
333 // exponent==0x7ff fraction==0
334 return !SAL_MATH_FINITE(d) &&
335 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0)
336 && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
337 == 0);
340 /** Test on any QNAN or SNAN.
342 inline bool isNan(double d)
344 // exponent==0x7ff fraction!=0
345 return !SAL_MATH_FINITE(d) && (
346 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0)
347 || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
348 != 0) );
351 /** If the sign bit is set.
353 inline bool isSignBitSet(double d)
355 return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0;
358 /** Set to +INF if bNegative==false or -INF if bNegative==true.
360 inline void setInf(double * pd, bool bNegative)
362 union
364 double sd;
365 sal_math_Double md;
367 md.w32_parts.msw = bNegative ? 0xFFF00000 : 0x7FF00000;
368 md.w32_parts.lsw = 0;
369 *pd = sd;
372 /** Set a QNAN.
374 inline void setNan(double * pd)
376 union
378 double sd;
379 sal_math_Double md;
381 md.w32_parts.msw = 0x7FFFFFFF;
382 md.w32_parts.lsw = 0xFFFFFFFF;
383 *pd = sd;
386 /** If a value is a valid argument for sin(), cos(), tan().
388 IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
389 radian must be supported by trigonometric functions. Unfortunately, at
390 least on x86 architectures, the FPU doesn't generate an error pattern for
391 values >2^64 but produces erroneous results instead and sets only the
392 "invalid operation" (IM) flag in the status word :-( Thus the application
393 has to handle it itself.
395 inline bool isValidArcArg(double d)
397 return fabs(d)
398 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
399 * static_cast< double >(static_cast< unsigned long >(0x80000000))
400 * 2);
403 /** Safe sin(), returns NAN if not valid.
405 inline double sin(double d)
407 if ( isValidArcArg( d ) )
408 return ::sin( d );
409 setNan( &d );
410 return d;
413 /** Safe cos(), returns NAN if not valid.
415 inline double cos(double d)
417 if ( isValidArcArg( d ) )
418 return ::cos( d );
419 setNan( &d );
420 return d;
423 /** Safe tan(), returns NAN if not valid.
425 inline double tan(double d)
427 if ( isValidArcArg( d ) )
428 return ::tan( d );
429 setNan( &d );
430 return d;
437 #endif // INCLUDED_RTL_MATH_HXX
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */