Version 5.2.6.1, tag libreoffice-5.2.6.1
[LibreOffice.git] / include / rtl / math.hxx
blob642763dfc2d77120b8f5f13353b36124a2addc46
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 <cstddef>
31 #include <math.h>
33 namespace rtl {
35 namespace math {
37 /** A wrapper around rtl_math_doubleToString.
39 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
40 sal_Int32 nDecPlaces,
41 sal_Char cDecSeparator,
42 sal_Int32 const * pGroups,
43 sal_Char cGroupSeparator,
44 bool bEraseTrailingDecZeros = false)
46 rtl::OString aResult;
47 rtl_math_doubleToString(&aResult.pData, NULL, 0, fValue, eFormat, nDecPlaces,
48 cDecSeparator, pGroups, cGroupSeparator,
49 bEraseTrailingDecZeros);
50 return aResult;
53 /** A wrapper around rtl_math_doubleToString, with no grouping.
55 inline rtl::OString doubleToString(double fValue, rtl_math_StringFormat eFormat,
56 sal_Int32 nDecPlaces,
57 sal_Char cDecSeparator,
58 bool bEraseTrailingDecZeros = false)
60 rtl::OString aResult;
61 rtl_math_doubleToString(&aResult.pData, NULL, 0, fValue, eFormat, nDecPlaces,
62 cDecSeparator, NULL, 0, bEraseTrailingDecZeros);
63 return aResult;
66 /** A wrapper around rtl_math_doubleToUString.
68 inline rtl::OUString doubleToUString(double fValue,
69 rtl_math_StringFormat eFormat,
70 sal_Int32 nDecPlaces,
71 sal_Unicode cDecSeparator,
72 sal_Int32 const * pGroups,
73 sal_Unicode cGroupSeparator,
74 bool bEraseTrailingDecZeros = false)
76 rtl::OUString aResult;
77 rtl_math_doubleToUString(&aResult.pData, NULL, 0, fValue, eFormat, nDecPlaces,
78 cDecSeparator, pGroups, cGroupSeparator,
79 bEraseTrailingDecZeros);
80 return aResult;
83 /** A wrapper around rtl_math_doubleToUString, with no grouping.
85 inline rtl::OUString doubleToUString(double fValue,
86 rtl_math_StringFormat eFormat,
87 sal_Int32 nDecPlaces,
88 sal_Unicode cDecSeparator,
89 bool bEraseTrailingDecZeros = false)
91 rtl::OUString aResult;
92 rtl_math_doubleToUString(&aResult.pData, NULL, 0, fValue, eFormat, nDecPlaces,
93 cDecSeparator, NULL, 0, bEraseTrailingDecZeros);
94 return aResult;
97 /** A wrapper around rtl_math_doubleToUString that appends to an
98 rtl::OUStringBuffer.
100 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
101 rtl_math_StringFormat eFormat,
102 sal_Int32 nDecPlaces,
103 sal_Unicode cDecSeparator,
104 sal_Int32 const * pGroups,
105 sal_Unicode cGroupSeparator,
106 bool bEraseTrailingDecZeros = false)
108 rtl_uString ** pData;
109 sal_Int32 * pCapacity;
110 rBuffer.accessInternals( &pData, &pCapacity );
111 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
112 eFormat, nDecPlaces, cDecSeparator, pGroups,
113 cGroupSeparator, bEraseTrailingDecZeros);
116 /** A wrapper around rtl_math_doubleToUString that appends to an
117 rtl::OUStringBuffer, with no grouping.
119 inline void doubleToUStringBuffer( rtl::OUStringBuffer& rBuffer, double fValue,
120 rtl_math_StringFormat eFormat,
121 sal_Int32 nDecPlaces,
122 sal_Unicode cDecSeparator,
123 bool bEraseTrailingDecZeros = false)
125 rtl_uString ** pData;
126 sal_Int32 * pCapacity;
127 rBuffer.accessInternals( &pData, &pCapacity );
128 rtl_math_doubleToUString( pData, pCapacity, rBuffer.getLength(), fValue,
129 eFormat, nDecPlaces, cDecSeparator, NULL, 0,
130 bEraseTrailingDecZeros);
133 /** A wrapper around rtl_math_stringToDouble.
135 inline double stringToDouble(rtl::OString const & rString,
136 sal_Char cDecSeparator, sal_Char cGroupSeparator,
137 rtl_math_ConversionStatus * pStatus = NULL,
138 sal_Int32 * pParsedEnd = NULL)
140 sal_Char const * pBegin = rString.getStr();
141 sal_Char const * pEnd;
142 double fResult = rtl_math_stringToDouble(pBegin,
143 pBegin + rString.getLength(),
144 cDecSeparator, cGroupSeparator,
145 pStatus, &pEnd);
146 if (pParsedEnd != NULL)
147 *pParsedEnd = (sal_Int32)(pEnd - pBegin);
148 return fResult;
151 /** A wrapper around rtl_math_uStringToDouble.
153 inline double stringToDouble(rtl::OUString const & rString,
154 sal_Unicode cDecSeparator,
155 sal_Unicode cGroupSeparator,
156 rtl_math_ConversionStatus * pStatus = NULL,
157 sal_Int32 * pParsedEnd = NULL)
159 sal_Unicode const * pBegin = rString.getStr();
160 sal_Unicode const * pEnd;
161 double fResult = rtl_math_uStringToDouble(pBegin,
162 pBegin + rString.getLength(),
163 cDecSeparator, cGroupSeparator,
164 pStatus, &pEnd);
165 if (pParsedEnd != NULL)
166 *pParsedEnd = (sal_Int32)(pEnd - pBegin);
167 return fResult;
170 /** A wrapper around rtl_math_round.
172 inline double round(
173 double fValue, int nDecPlaces = 0,
174 rtl_math_RoundingMode eMode = rtl_math_RoundingMode_Corrected)
176 return rtl_math_round(fValue, nDecPlaces, eMode);
179 /** A wrapper around rtl_math_pow10Exp.
181 inline double pow10Exp(double fValue, int nExp)
183 return rtl_math_pow10Exp(fValue, nExp);
186 /** A wrapper around rtl_math_approxValue.
188 inline double approxValue(double fValue)
190 return rtl_math_approxValue(fValue);
193 /** A wrapper around rtl_math_expm1.
195 inline double expm1(double fValue)
197 return rtl_math_expm1(fValue);
200 /** A wrapper around rtl_math_log1p.
202 inline double log1p(double fValue)
204 return rtl_math_log1p(fValue);
207 /** A wrapper around rtl_math_atanh.
209 inline double atanh(double fValue)
211 return rtl_math_atanh(fValue);
214 /** A wrapper around rtl_math_erf.
216 inline double erf(double fValue)
218 return rtl_math_erf(fValue);
221 /** A wrapper around rtl_math_erfc.
223 inline double erfc(double fValue)
225 return rtl_math_erfc(fValue);
228 /** A wrapper around rtl_math_asinh.
230 inline double asinh(double fValue)
232 return rtl_math_asinh(fValue);
235 /** A wrapper around rtl_math_acosh.
237 inline double acosh(double fValue)
239 return rtl_math_acosh(fValue);
243 /** Test equality of two values with an accuracy of the magnitude of the
244 given values scaled by 2^-48 (4 bits roundoff stripped).
246 @attention
247 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
249 inline bool approxEqual(double a, double b)
251 if ( a == b )
252 return true;
253 double x = a - b;
254 return (x < 0.0 ? -x : x)
255 < ((a < 0.0 ? -a : a) * (1.0 / (16777216.0 * 16777216.0)));
258 /** Test equality of two values with an accuracy defined by nPrec
260 @attention
261 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
263 inline bool approxEqual(double a, double b, sal_Int16 nPrec)
265 if ( a == b )
266 return true;
267 double x = a - b;
268 return (x < 0.0 ? -x : x)
269 < ((a < 0.0 ? -a : a) * (1.0 / (pow(static_cast<double>(2.0), nPrec))));
271 /** Add two values.
273 If signs differ and the absolute values are equal according to approxEqual()
274 the method returns 0.0 instead of calculating the sum.
276 If you wanted to sum up multiple values it would be convenient not to call
277 approxAdd() for each value but instead remember the first value not equal to
278 0.0, add all other values using normal + operator, and with the result and
279 the remembered value call approxAdd().
281 inline double approxAdd(double a, double b)
283 if ( ((a < 0.0 && b > 0.0) || (b < 0.0 && a > 0.0))
284 && approxEqual( a, -b ) )
285 return 0.0;
286 return a + b;
289 /** Subtract two values (a-b).
291 If signs are identical and the values are equal according to approxEqual()
292 the method returns 0.0 instead of calculating the subtraction.
294 inline double approxSub(double a, double b)
296 if ( ((a < 0.0 && b < 0.0) || (a > 0.0 && b > 0.0)) && approxEqual( a, b ) )
297 return 0.0;
298 return a - b;
301 /** floor() method taking approxValue() into account.
303 Use for expected integer values being calculated by double functions.
305 inline double approxFloor(double a)
307 return floor( approxValue( a ));
310 /** ceil() method taking approxValue() into account.
312 Use for expected integer values being calculated by double functions.
314 inline double approxCeil(double a)
316 return ceil( approxValue( a ));
319 /** Tests whether a value is neither INF nor NAN.
321 inline bool isFinite(double d)
323 return SAL_MATH_FINITE(d);
326 /** If a value represents +INF or -INF.
328 The sign bit may be queried with isSignBitSet().
330 If isFinite(d)==false and isInf(d)==false then NAN.
332 inline bool isInf(double d)
334 // exponent==0x7ff fraction==0
335 return !SAL_MATH_FINITE(d) &&
336 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi == 0)
337 && (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
338 == 0);
341 /** Test on any QNAN or SNAN.
343 inline bool isNan(double d)
345 // exponent==0x7ff fraction!=0
346 return !SAL_MATH_FINITE(d) && (
347 (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_hi != 0)
348 || (reinterpret_cast< sal_math_Double * >(&d)->inf_parts.fraction_lo
349 != 0) );
352 /** If the sign bit is set.
354 inline bool isSignBitSet(double d)
356 return reinterpret_cast< sal_math_Double * >(&d)->inf_parts.sign != 0;
359 /** Set to +INF if bNegative==false or -INF if bNegative==true.
361 inline void setInf(double * pd, bool bNegative)
363 union
365 double sd;
366 sal_math_Double md;
368 md.w32_parts.msw = bNegative ? 0xFFF00000 : 0x7FF00000;
369 md.w32_parts.lsw = 0;
370 *pd = sd;
373 /** Set a QNAN.
375 inline void setNan(double * pd)
377 union
379 double sd;
380 sal_math_Double md;
382 md.w32_parts.msw = 0x7FFFFFFF;
383 md.w32_parts.lsw = 0xFFFFFFFF;
384 *pd = sd;
387 /** If a value is a valid argument for sin(), cos(), tan().
389 IEEE 754 specifies that absolute values up to 2^64 (=1.844e19) for the
390 radian must be supported by trigonometric functions. Unfortunately, at
391 least on x86 architectures, the FPU doesn't generate an error pattern for
392 values >2^64 but produces erroneous results instead and sets only the
393 "invalid operation" (IM) flag in the status word :-( Thus the application
394 has to handle it itself.
396 inline bool isValidArcArg(double d)
398 return fabs(d)
399 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
400 * static_cast< double >(static_cast< unsigned long >(0x80000000))
401 * 2);
404 /** Safe sin(), returns NAN if not valid.
406 inline double sin(double d)
408 if ( isValidArcArg( d ) )
409 return ::sin( d );
410 setNan( &d );
411 return d;
414 /** Safe cos(), returns NAN if not valid.
416 inline double cos(double d)
418 if ( isValidArcArg( d ) )
419 return ::cos( d );
420 setNan( &d );
421 return d;
424 /** Safe tan(), returns NAN if not valid.
426 inline double tan(double d)
428 if ( isValidArcArg( d ) )
429 return ::tan( d );
430 setNan( &d );
431 return d;
438 #endif // INCLUDED_RTL_MATH_HXX
440 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */