1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
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>
37 /** A wrapper around rtl_math_doubleToString.
39 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
41 sal_Char cDecSeparator
,
42 sal_Int32
const * pGroups
,
43 sal_Char cGroupSeparator
,
44 bool bEraseTrailingDecZeros
= false)
47 rtl_math_doubleToString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
48 cDecSeparator
, pGroups
, cGroupSeparator
,
49 bEraseTrailingDecZeros
);
53 /** A wrapper around rtl_math_doubleToString, with no grouping.
55 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
57 sal_Char cDecSeparator
,
58 bool bEraseTrailingDecZeros
= false)
61 rtl_math_doubleToString(&aResult
.pData
, NULL
, 0, fValue
, eFormat
, nDecPlaces
,
62 cDecSeparator
, NULL
, 0, bEraseTrailingDecZeros
);
66 /** A wrapper around rtl_math_doubleToUString.
68 inline rtl::OUString
doubleToUString(double fValue
,
69 rtl_math_StringFormat eFormat
,
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
);
83 /** A wrapper around rtl_math_doubleToUString, with no grouping.
85 inline rtl::OUString
doubleToUString(double fValue
,
86 rtl_math_StringFormat eFormat
,
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
);
97 /** A wrapper around rtl_math_doubleToUString that appends to an
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
,
146 if (pParsedEnd
!= NULL
)
147 *pParsedEnd
= (sal_Int32
)(pEnd
- pBegin
);
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
,
165 if (pParsedEnd
!= NULL
)
166 *pParsedEnd
= (sal_Int32
)(pEnd
- pBegin
);
170 /** A wrapper around rtl_math_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).
247 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
249 inline bool approxEqual(double a
, double 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
261 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
263 inline bool approxEqual(double a
, double b
, sal_Int16 nPrec
)
268 return (x
< 0.0 ? -x
: x
)
269 < ((a
< 0.0 ? -a
: a
) * (1.0 / (pow(static_cast<double>(2.0), nPrec
))));
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
) )
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
) )
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
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
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
)
368 md
.w32_parts
.msw
= bNegative
? 0xFFF00000 : 0x7FF00000;
369 md
.w32_parts
.lsw
= 0;
375 inline void setNan(double * pd
)
382 md
.w32_parts
.msw
= 0x7FFFFFFF;
383 md
.w32_parts
.lsw
= 0xFFFFFFFF;
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
)
399 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
400 * static_cast< double >(static_cast< unsigned long >(0x80000000))
404 /** Safe sin(), returns NAN if not valid.
406 inline double sin(double d
)
408 if ( isValidArcArg( d
) )
414 /** Safe cos(), returns NAN if not valid.
416 inline double cos(double d
)
418 if ( isValidArcArg( d
) )
424 /** Safe tan(), returns NAN if not valid.
426 inline double tan(double d
)
428 if ( isValidArcArg( d
) )
438 #endif // INCLUDED_RTL_MATH_HXX
440 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */