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>
36 /** A wrapper around rtl_math_doubleToString.
38 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
40 sal_Char cDecSeparator
,
41 sal_Int32
const * pGroups
,
42 sal_Char cGroupSeparator
,
43 bool bEraseTrailingDecZeros
= false)
46 rtl_math_doubleToString(&aResult
.pData
, 0, 0, fValue
, eFormat
, nDecPlaces
,
47 cDecSeparator
, pGroups
, cGroupSeparator
,
48 bEraseTrailingDecZeros
);
52 /** A wrapper around rtl_math_doubleToString, with no grouping.
54 inline rtl::OString
doubleToString(double fValue
, rtl_math_StringFormat eFormat
,
56 sal_Char cDecSeparator
,
57 bool bEraseTrailingDecZeros
= false)
60 rtl_math_doubleToString(&aResult
.pData
, 0, 0, fValue
, eFormat
, nDecPlaces
,
61 cDecSeparator
, 0, 0, bEraseTrailingDecZeros
);
65 /** A wrapper around rtl_math_doubleToUString.
67 inline rtl::OUString
doubleToUString(double fValue
,
68 rtl_math_StringFormat eFormat
,
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
);
82 /** A wrapper around rtl_math_doubleToUString, with no grouping.
84 inline rtl::OUString
doubleToUString(double fValue
,
85 rtl_math_StringFormat eFormat
,
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
);
96 /** A wrapper around rtl_math_doubleToUString that appends to an
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
,
146 *pParsedEnd
= (sal_Int32
)(pEnd
- pBegin
);
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
,
165 *pParsedEnd
= (sal_Int32
)(pEnd
- pBegin
);
169 /** A wrapper around rtl_math_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).
246 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
248 inline bool approxEqual(double a
, double 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
260 approxEqual( value!=0.0, 0.0 ) _never_ yields true.
262 inline bool approxEqual(double a
, double b
, sal_Int16 nPrec
)
267 return (x
< 0.0 ? -x
: x
)
268 < ((a
< 0.0 ? -a
: a
) * (1.0 / (pow(static_cast<double>(2.0), nPrec
))));
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
) )
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
) )
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
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
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
)
367 md
.w32_parts
.msw
= bNegative
? 0xFFF00000 : 0x7FF00000;
368 md
.w32_parts
.lsw
= 0;
374 inline void setNan(double * pd
)
381 md
.w32_parts
.msw
= 0x7FFFFFFF;
382 md
.w32_parts
.lsw
= 0xFFFFFFFF;
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
)
398 <= (static_cast< double >(static_cast< unsigned long >(0x80000000))
399 * static_cast< double >(static_cast< unsigned long >(0x80000000))
403 /** Safe sin(), returns NAN if not valid.
405 inline double sin(double d
)
407 if ( isValidArcArg( d
) )
413 /** Safe cos(), returns NAN if not valid.
415 inline double cos(double d
)
417 if ( isValidArcArg( d
) )
423 /** Safe tan(), returns NAN if not valid.
425 inline double tan(double d
)
427 if ( isValidArcArg( d
) )
437 #endif // INCLUDED_RTL_MATH_HXX
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */