android: Update app-specific/MIME type icons
[LibreOffice.git] / sal / qa / rtl / math / test-rtl-math.cxx
blob05879d567760bd109097979961bb0ab4d9565374
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 #include <sal/types.h>
21 #include <cppunit/TestAssert.h>
22 #include <cppunit/TestFixture.h>
23 #include <cppunit/extensions/HelperMacros.h>
24 #include <cppunit/plugin/TestPlugIn.h>
25 #include <rtl/math.hxx>
26 #include <rtl/ustring.h>
27 #include <rtl/ustring.hxx>
28 #include <limits>
30 template<> inline std::string CPPUNIT_NS::assertion_traits<rtl_math_ConversionStatus>::toString(
31 const rtl_math_ConversionStatus& x )
33 OStringStream ost;
34 ost << static_cast<unsigned int>(x);
35 return ost.str();
38 namespace {
40 class Test: public CppUnit::TestFixture {
41 public:
42 void test_stringToDouble_good() {
43 rtl_math_ConversionStatus status;
44 sal_Int32 end;
45 double res = rtl::math::stringToDouble(
46 " +1.E01foo",
47 '.', ',', &status, &end);
48 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
49 CPPUNIT_ASSERT_EQUAL(RTL_CONSTASCII_LENGTH(" +1.E01"), end);
50 CPPUNIT_ASSERT_EQUAL(10.0, res);
52 res = rtl::math::stringToDouble(
53 "NaN",
54 '.', ',', &status, &end);
55 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
56 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), end);
57 CPPUNIT_ASSERT(std::isnan(res));
59 res = rtl::math::stringToDouble(
60 "NaN1.23",
61 '.', ',', &status, &end);
62 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
63 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), end);
64 CPPUNIT_ASSERT(std::isnan(res));
66 res = rtl::math::stringToDouble(
67 "+NaN",
68 '.', ',', &status, &end);
69 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
70 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
71 CPPUNIT_ASSERT_EQUAL(0.0, res);
73 res = rtl::math::stringToDouble(
74 "-NaN",
75 '.', ',', &status, &end);
76 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
77 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
78 CPPUNIT_ASSERT_EQUAL(0.0, res);
80 res = rtl::math::stringToDouble(
81 "+1.#NAN",
82 '.', ',', &status, &end);
83 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
84 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), end);
85 CPPUNIT_ASSERT(std::isnan(res));
86 CPPUNIT_ASSERT(!std::signbit(res));
88 res = rtl::math::stringToDouble(
89 "-1.#NAN",
90 '.', ',', &status, &end);
91 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
92 CPPUNIT_ASSERT_EQUAL(sal_Int32(7), end);
93 CPPUNIT_ASSERT(std::isnan(res));
94 CPPUNIT_ASSERT(std::signbit(res));
96 res = rtl::math::stringToDouble(
97 "INF",
98 '.', ',', &status, &end);
99 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_OutOfRange, status);
100 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), end);
101 CPPUNIT_ASSERT(std::isinf(res));
103 res = rtl::math::stringToDouble(
104 "INF1.23",
105 '.', ',', &status, &end);
106 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_OutOfRange, status);
107 CPPUNIT_ASSERT_EQUAL(sal_Int32(3), end);
108 CPPUNIT_ASSERT(std::isinf(res));
110 res = rtl::math::stringToDouble(
111 ".5",
112 '.', ',', &status, &end);
113 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
114 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), end);
115 CPPUNIT_ASSERT_EQUAL(0.5, res);
117 res = rtl::math::stringToDouble(
118 "5.",
119 '.', ',', &status, &end);
120 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
121 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), end);
122 CPPUNIT_ASSERT_EQUAL(5.0, res);
124 // Leading 0 and group separator.
125 res = rtl::math::stringToDouble(
126 "0,123",
127 '.', ',', &status, &end);
128 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
129 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), end);
130 CPPUNIT_ASSERT_EQUAL(123.0, res);
132 // Leading 0 and two consecutive group separators are none.
133 res = rtl::math::stringToDouble(
134 "0,,1",
135 '.', ',', &status, &end);
136 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
137 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), end);
138 CPPUNIT_ASSERT_EQUAL(0.0, res);
140 // Leading 0 and group separator at end is none.
141 res = rtl::math::stringToDouble(
142 "0,",
143 '.', ',', &status, &end);
144 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
145 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), end);
146 CPPUNIT_ASSERT_EQUAL(0.0, res);
148 // Leading 0 and group separator before non-digit is none.
149 res = rtl::math::stringToDouble(
150 "0,x",
151 '.', ',', &status, &end);
152 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
153 CPPUNIT_ASSERT_EQUAL(sal_Int32(1), end);
154 CPPUNIT_ASSERT_EQUAL(0.0, res);
156 // Trailing group separator is none.
157 res = rtl::math::stringToDouble(
158 "1,234,",
159 '.', ',', &status, &end);
160 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
161 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), end);
162 CPPUNIT_ASSERT_EQUAL(1234.0, res);
164 // Group separator followed by non-digit is none.
165 res = rtl::math::stringToDouble(
166 "1,234,x",
167 '.', ',', &status, &end);
168 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
169 CPPUNIT_ASSERT_EQUAL(sal_Int32(5), end);
170 CPPUNIT_ASSERT_EQUAL(1234.0, res);
172 // Check that the value is the nearest double-precision representation of the decimal 0.0042
173 // (it was 0.0042000000000000006 instead of 0.0041999999999999997)
174 res = rtl::math::stringToDouble("0,0042", ',', ' ', &status, &end);
175 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
176 CPPUNIT_ASSERT_EQUAL(0.0042, res);
178 // "- 1" is nothing
179 res = rtl::math::stringToDouble("- 1", '.', ',', &status, &end);
180 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
181 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
182 CPPUNIT_ASSERT_EQUAL(0.0, res);
184 // "-1E+E" : no exponent
185 res = rtl::math::stringToDouble("-1E+E", '.', ',', &status, &end);
186 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
187 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), end);
188 CPPUNIT_ASSERT_EQUAL(-1.0, res);
190 // "-0" is negative zero
191 res = rtl::math::stringToDouble("-0", '.', ',', &status, &end);
192 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
193 CPPUNIT_ASSERT_EQUAL(sal_Int32(2), end);
194 CPPUNIT_ASSERT_EQUAL(0.0, res);
195 CPPUNIT_ASSERT(std::signbit(res));
197 // Compensating: "0.001E311" is 1E308, not overflow/inf
198 res = rtl::math::stringToDouble("0.001E311", '.', ',', &status, &end);
199 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
200 CPPUNIT_ASSERT_EQUAL(sal_Int32(9), end);
201 CPPUNIT_ASSERT_EQUAL(1E308, res);
203 res = rtl::math::stringToDouble("1E8589934590", '.', ',', &status, &end);
204 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_OutOfRange, status);
205 CPPUNIT_ASSERT_EQUAL(sal_Int32(12), end);
206 CPPUNIT_ASSERT_EQUAL(std::numeric_limits<double>::infinity(), res);
208 // DBL_MAX and 4 nextafters
209 double fValAfter = DBL_MAX;
210 res = rtl::math::stringToDouble("1.7976931348623157e+308", '.', ',', &status, &end);
211 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
212 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), end);
213 CPPUNIT_ASSERT_EQUAL(fValAfter, res);
215 fValAfter = std::nextafter( fValAfter, 0);
216 res = rtl::math::stringToDouble("1.7976931348623155e+308", '.', ',', &status, &end);
217 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
218 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), end);
219 CPPUNIT_ASSERT_EQUAL(fValAfter, res);
221 fValAfter = std::nextafter( fValAfter, 0);
222 res = rtl::math::stringToDouble("1.7976931348623153e+308", '.', ',', &status, &end);
223 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
224 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), end);
225 CPPUNIT_ASSERT_EQUAL(fValAfter, res);
227 fValAfter = std::nextafter( fValAfter, 0);
228 res = rtl::math::stringToDouble("1.7976931348623151e+308", '.', ',', &status, &end);
229 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
230 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), end);
231 CPPUNIT_ASSERT_EQUAL(fValAfter, res);
233 fValAfter = std::nextafter( fValAfter, 0);
234 res = rtl::math::stringToDouble("1.7976931348623149e+308", '.', ',', &status, &end);
235 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
236 CPPUNIT_ASSERT_EQUAL(sal_Int32(23), end);
237 CPPUNIT_ASSERT_EQUAL(fValAfter, res);
240 void test_stringToDouble_bad() {
241 rtl_math_ConversionStatus status;
242 sal_Int32 end;
243 double res = rtl::math::stringToDouble(
244 " +Efoo",
245 '.', ',', &status, &end);
246 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
247 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
248 CPPUNIT_ASSERT_EQUAL(0.0, res);
250 res = rtl::math::stringToDouble(
251 ".",
252 '.', ',', &status, &end);
253 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
254 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
255 CPPUNIT_ASSERT_EQUAL(0.0, res);
257 res = rtl::math::stringToDouble(
258 " +.Efoo",
259 '.', ',', &status, &end);
260 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
261 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
262 CPPUNIT_ASSERT_EQUAL(0.0, res);
264 res = rtl::math::stringToDouble(
265 " +,.Efoo",
266 '.', ',', &status, &end);
267 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
268 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
269 CPPUNIT_ASSERT_EQUAL(0.0, res);
271 // Leading group separator is none.
272 res = rtl::math::stringToDouble(
273 ",1234",
274 '.', ',', &status, &end);
275 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
276 CPPUNIT_ASSERT_EQUAL(sal_Int32(0), end);
277 CPPUNIT_ASSERT_EQUAL(0.0, res);
280 void test_stringToDouble_exponent_without_digit() {
281 rtl_math_ConversionStatus status;
282 sal_Int32 end;
283 double res = rtl::math::stringToDouble(
284 "1e",
285 '.', ',', &status, &end);
286 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
287 CPPUNIT_ASSERT_EQUAL(RTL_CONSTASCII_LENGTH("1"), end);
288 CPPUNIT_ASSERT_EQUAL(1.0, res);
289 res = rtl::math::stringToDouble(
290 "0e",
291 '.', ',', &status, &end);
292 CPPUNIT_ASSERT_EQUAL(rtl_math_ConversionStatus_Ok, status);
293 CPPUNIT_ASSERT_EQUAL(RTL_CONSTASCII_LENGTH("1"), end);
294 CPPUNIT_ASSERT_EQUAL(0.0, res);
297 void test_round() {
298 double fVal = 5000000000000001.0;
299 CPPUNIT_ASSERT_EQUAL( 5000000000000001.0, rtl::math::round( fVal, 9, rtl_math_RoundingMode_Corrected));
301 fVal = 8796093022188.0;
302 CPPUNIT_ASSERT_EQUAL( 6093022188.0 , rtl::math::round( fVal, 9, rtl_math_RoundingMode_Corrected) - 8790000000000);
304 fVal = 4503599627370491.0;
305 CPPUNIT_ASSERT_EQUAL( 4503599627370000.0, rtl::math::round( fVal, -3, rtl_math_RoundingMode_Corrected));
308 void test_doubleToString() {
309 double fVal = 999999999999999.0;
310 sal_Int32 aGroups[3] = { 3, 2, 0 };
311 OUString aRes( rtl::math::doubleToUString( fVal,
312 rtl_math_StringFormat_Automatic,
313 rtl_math_DecimalPlaces_Max,
314 '.', aGroups, ',', true));
315 CPPUNIT_ASSERT_EQUAL( OUString("99,99,99,99,99,99,999"), aRes);
317 fVal = 949.0;
318 aRes = rtl::math::doubleToUString( fVal,
319 rtl_math_StringFormat_Automatic,
320 -2, // round before decimals
321 '.', aGroups, ',', true);
322 CPPUNIT_ASSERT_EQUAL( OUString("900"), aRes);
324 fVal = 950.0;
325 aRes = rtl::math::doubleToUString( fVal,
326 rtl_math_StringFormat_Automatic,
327 -2, // round before decimals
328 '.', aGroups, ',', true);
329 CPPUNIT_ASSERT_EQUAL( OUString("1,000"), aRes);
331 // Check non-ASCII separators: Arabic decimal separator U+066B, thousand separator U+066C
332 fVal = 123456.78;
333 aRes = rtl::math::doubleToUString( fVal,
334 rtl_math_StringFormat_Automatic,
336 u'Ù«', aGroups, u'Ù¬', true);
337 CPPUNIT_ASSERT_EQUAL( OUString(u"1Ù¬23Ù¬456Ù«78"), aRes);
339 fVal = 4503599627370495.0;
340 aRes = rtl::math::doubleToUString( fVal,
341 rtl_math_StringFormat_Automatic,
342 rtl_math_DecimalPlaces_Max, '.');
343 CPPUNIT_ASSERT_EQUAL( OUString("4503599627370495"), aRes);
345 fVal = 4503599627370496.0;
346 aRes = rtl::math::doubleToUString( fVal,
347 rtl_math_StringFormat_Automatic,
348 2, '.');
349 CPPUNIT_ASSERT_EQUAL( OUString("4503599627370496.00"), aRes);
351 fVal = -4503599627370496.0;
352 aRes = rtl::math::doubleToUString( fVal,
353 rtl_math_StringFormat_Automatic,
354 2, '.');
355 CPPUNIT_ASSERT_EQUAL( OUString("-4503599627370496.00"), aRes);
357 fVal = 9007199254740991.0; // (2^53)-1
358 aRes = rtl::math::doubleToUString( fVal,
359 rtl_math_StringFormat_Automatic,
360 rtl_math_DecimalPlaces_Max, '.', true);
361 CPPUNIT_ASSERT_EQUAL( OUString("9007199254740991"), aRes);
363 fVal = 9007199254740992.0; // (2^53), algorithm switch
364 aRes = rtl::math::doubleToUString( fVal,
365 rtl_math_StringFormat_Automatic,
366 rtl_math_DecimalPlaces_Max, '.', true);
367 CPPUNIT_ASSERT_EQUAL( OUString("9.00719925474099E+015"), aRes);
369 fVal = 9007199254740993.0; // (2^53)+1 would be but is 9007199254740992
370 aRes = rtl::math::doubleToUString( fVal,
371 rtl_math_StringFormat_Automatic,
372 rtl_math_DecimalPlaces_Max, '.', true);
373 CPPUNIT_ASSERT_EQUAL( OUString("9.00719925474099E+015"), aRes);
375 // Test rtl_math_StringFormat_G
377 fVal = 0.001234567;
378 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 3, '.', true);
379 CPPUNIT_ASSERT_EQUAL( OUString("0.00123"), aRes);
381 fVal = 123.4567;
382 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 3, '.', true);
383 CPPUNIT_ASSERT_EQUAL( OUString("123"), aRes);
385 fVal = 123.4567;
386 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 4, '.', true);
387 CPPUNIT_ASSERT_EQUAL( OUString("123.5"), aRes);
389 fVal = 99.6;
390 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 3, '.', true);
391 CPPUNIT_ASSERT_EQUAL( OUString("99.6"), aRes);
393 // Expected could be 1E+03 (as 999.6 rounded to 3 significant digits
394 // results in 1000 with an exponent equal to significant digits).
395 // Currently we don't and output 1000 instead, negligible.
396 fVal = 999.6;
397 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 3, '.', true);
398 CPPUNIT_ASSERT_EQUAL( OUString("1000"), aRes);
400 fVal = 9999.6;
401 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, 3, '.', true);
402 CPPUNIT_ASSERT_EQUAL( OUString("1E+004"), aRes);
404 fVal = 12345.6789;
405 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_G, -3, '.', true);
406 CPPUNIT_ASSERT_EQUAL( OUString("1.2E+004"), aRes);
408 // DBL_MAX and 4 nextafters
409 fVal = DBL_MAX;
410 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic,
411 rtl_math_DecimalPlaces_Max, '.', true);
412 CPPUNIT_ASSERT_EQUAL( OUString("1.7976931348623157E+308"), aRes);
414 fVal = std::nextafter( fVal, 0);
415 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic,
416 rtl_math_DecimalPlaces_Max, '.', true);
417 CPPUNIT_ASSERT_EQUAL( OUString("1.7976931348623155E+308"), aRes);
419 fVal = std::nextafter( fVal, 0);
420 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic,
421 rtl_math_DecimalPlaces_Max, '.', true);
422 CPPUNIT_ASSERT_EQUAL( OUString("1.7976931348623153E+308"), aRes);
424 fVal = std::nextafter( fVal, 0);
425 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic,
426 rtl_math_DecimalPlaces_Max, '.', true);
427 CPPUNIT_ASSERT_EQUAL( OUString("1.7976931348623151E+308"), aRes);
429 fVal = std::nextafter( fVal, 0);
430 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic,
431 rtl_math_DecimalPlaces_Max, '.', true);
432 CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862315E+308"), aRes);
433 CPPUNIT_ASSERT_EQUAL(fVal, rtl::math::stringToDouble(aRes, '.', ',')); // Test roundtrip
435 // DBL_MAX and 4 nextafters rounded to 15 decimals
436 fVal = DBL_MAX;
437 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 15, '.', true);
438 CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862316E+308"), aRes);
440 fVal = std::nextafter( fVal, 0);
441 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 15, '.', true);
442 CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862316E+308"), aRes);
444 fVal = std::nextafter( fVal, 0);
445 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 15, '.', true);
446 CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862315E+308"), aRes);
448 fVal = std::nextafter( fVal, 0);
449 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 15, '.', true);
450 CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862315E+308"), aRes);
452 fVal = std::nextafter( fVal, 0);
453 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 15, '.', true);
454 CPPUNIT_ASSERT_EQUAL( OUString("1.797693134862315E+308"), aRes);
456 // DBL_MAX rounded to 14 decimals
457 fVal = DBL_MAX;
458 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 14, '.', true);
459 CPPUNIT_ASSERT_EQUAL( OUString("1.79769313486232E+308"), aRes);
461 // DBL_MAX rounded to 2 decimals
462 fVal = DBL_MAX;
463 aRes = rtl::math::doubleToUString( fVal, rtl_math_StringFormat_Automatic, 2, '.', true);
464 CPPUNIT_ASSERT_EQUAL( OUString("1.8E+308"), aRes);
466 // Crashed after commit eae24a9488814e77254d175c11fc4a138c1dbd30
467 fVal = 123456.789;
468 aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_E, 2, '.', false);
469 CPPUNIT_ASSERT_EQUAL(OUString("1.23E+005"), aRes);
471 fVal = 9.9999999999999929;
472 aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
473 CPPUNIT_ASSERT_EQUAL(OUString("9.99999999999999"), aRes);
475 fVal = 0.99999999999999933;
476 aRes = rtl::math::doubleToUString(fVal, rtl_math_StringFormat_F, rtl_math_DecimalPlaces_Max, '.', true);
477 CPPUNIT_ASSERT_EQUAL(OUString("0.999999999999999"), aRes);
480 void test_approx() {
481 // (2^53)-1 , (2^53)-3
482 CPPUNIT_ASSERT_EQUAL( false, rtl::math::approxEqual( 9007199254740991.0, 9007199254740989.0));
483 // (2^53)-1 , (2^53)-2
484 CPPUNIT_ASSERT_EQUAL( false, rtl::math::approxEqual( 9007199254740991.0, 9007199254740990.0));
485 // Note: the following are internally represented as 900719925474099.12
486 // and 900719925474098.88 and the difference is 0.25 ...
487 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 900719925474099.1, 900719925474098.9));
488 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 72.944444444444443, 72.9444444444444));
489 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 359650.27322404372, 359650.27322404401));
490 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 5.3590326375710063e+238, 5.3590326375710109e+238));
491 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 7.4124095894894475e+158, 7.4124095894894514e+158));
492 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 1.2905754687023132e+79, 1.2905754687023098e+79));
493 CPPUNIT_ASSERT_EQUAL( true, rtl::math::approxEqual( 3.5612905090455637e+38, 3.5612905090455599e+38));
494 // 0.3 - 0.2 - 0.1 == 0.0
495 CPPUNIT_ASSERT_EQUAL( 0.0, rtl::math::approxSub( rtl::math::approxSub( 0.3, 0.2), 0.1));
496 // ((2^53)-1) - ((2^53)-2) == 1.0
497 CPPUNIT_ASSERT_EQUAL( 1.0, rtl::math::approxSub( 9007199254740991.0, 9007199254740990.0));
498 // (3^31) - ((3^31)-1) == 1.0
499 CPPUNIT_ASSERT_EQUAL( 1.0, rtl::math::approxSub( 617673396283947.0, 617673396283946.0));
502 void test_erf() {
503 double x, res;
504 x = 0.0;
505 res = rtl::math::erf(x);
506 CPPUNIT_ASSERT_EQUAL(0.0,res);
507 rtl::math::setInf( &x, false);
508 res = rtl::math::erf(x);
509 CPPUNIT_ASSERT_EQUAL(1.0,res);
510 rtl::math::setInf( &x, true);
511 res = rtl::math::erf(x);
512 CPPUNIT_ASSERT_EQUAL(-1.0,res);
513 rtl::math::setNan( &x);
514 res = rtl::math::erf(x);
515 CPPUNIT_ASSERT(std::isnan(res));
516 x = 3.0;
517 res = rtl::math::erf(-x);
518 CPPUNIT_ASSERT_DOUBLES_EQUAL( -rtl::math::erf(x), res, 1E-12);
521 void test_erfc() {
522 double x, res;
523 x = 0.0;
524 res = rtl::math::erfc(x);
525 CPPUNIT_ASSERT_EQUAL(1.0,res);
526 rtl::math::setInf( &x, false);
527 res = rtl::math::erfc(x);
528 CPPUNIT_ASSERT_EQUAL(0.0,res);
529 rtl::math::setInf( &x, true);
530 res = rtl::math::erfc(x);
531 CPPUNIT_ASSERT_EQUAL(2.0,res);
532 rtl::math::setNan( &x);
533 res = rtl::math::erfc(x);
534 CPPUNIT_ASSERT(std::isnan(res));
535 x = 3.0;
536 res = rtl::math::erfc(-x);
537 CPPUNIT_ASSERT_DOUBLES_EQUAL( 2.0 - rtl::math::erfc(x), res, 1E-12);
540 void test_expm1() {
541 double x, res;
542 x = 0.0;
543 res = rtl::math::expm1(x);
544 CPPUNIT_ASSERT_EQUAL(0.0,res);
545 x = -0.0;
546 res = rtl::math::expm1(x);
547 CPPUNIT_ASSERT_EQUAL(-0.0,res);
548 CPPUNIT_ASSERT(std::signbit(res));
549 rtl::math::setInf( &x, false);
550 res = rtl::math::expm1(x);
551 CPPUNIT_ASSERT_EQUAL(true, std::isinf(res) && !std::signbit(res));
552 rtl::math::setInf( &x, true);
553 res = rtl::math::expm1(x);
554 CPPUNIT_ASSERT_EQUAL(-1.0,res);
555 rtl::math::setNan( &x);
556 res = rtl::math::expm1(x);
557 CPPUNIT_ASSERT(std::isnan(res));
560 void test_log1p() {
561 double x, res;
562 x = 0.0;
563 res = rtl::math::log1p(x);
564 CPPUNIT_ASSERT_EQUAL(0.0,res);
565 x = -0.0;
566 res = rtl::math::log1p(x);
567 CPPUNIT_ASSERT_EQUAL(-0.0,res);
568 CPPUNIT_ASSERT(std::signbit(res));
569 rtl::math::setInf( &x, false);
570 res = rtl::math::log1p(x);
571 CPPUNIT_ASSERT_EQUAL(true, std::isinf(res) && !std::signbit(res));
572 x = -1.0;
573 res = rtl::math::log1p(x);
574 CPPUNIT_ASSERT_EQUAL(true, std::isinf(res) && std::signbit(res));
575 x = -1.1;
576 res = rtl::math::log1p(x);
577 CPPUNIT_ASSERT(std::isnan(res));
578 rtl::math::setInf( &x, true);
579 res = rtl::math::log1p(x);
580 CPPUNIT_ASSERT(std::isnan(res));
581 rtl::math::setNan( &x);
582 res = rtl::math::log1p(x);
583 CPPUNIT_ASSERT(std::isnan(res));
586 void test_acosh() {
587 double res;
589 res = rtl::math::acosh(-1.0); // NaN
590 CPPUNIT_ASSERT(std::isnan(res));
592 res = rtl::math::acosh(0.0); // NaN
593 CPPUNIT_ASSERT(std::isnan(res));
595 res = rtl::math::acosh(0.5); // NaN
596 CPPUNIT_ASSERT(std::isnan(res));
598 CPPUNIT_ASSERT_EQUAL(0.0, rtl::math::acosh(1.0));
600 res = rtl::math::acosh(std::numeric_limits<double>::infinity()); // +Inf
601 CPPUNIT_ASSERT(!std::signbit(res));
602 CPPUNIT_ASSERT(std::isinf(res));
604 // #i97605
605 CPPUNIT_ASSERT_DOUBLES_EQUAL(692.56728736744176, rtl::math::acosh(3e+300), 1e-15);
606 CPPUNIT_ASSERT_DOUBLES_EQUAL(0.014142017775252324, rtl::math::acosh(1.0001), 1e-15);
609 void test_asinh() {
610 double res;
612 res = rtl::math::asinh(-std::numeric_limits<double>::infinity()); // -Inf
613 CPPUNIT_ASSERT(std::signbit(res));
614 CPPUNIT_ASSERT(std::isinf(res));
616 CPPUNIT_ASSERT_EQUAL(0.0, rtl::math::asinh(0.0));
618 res = rtl::math::asinh(std::numeric_limits<double>::infinity()); // +Inf
619 CPPUNIT_ASSERT(!std::signbit(res));
620 CPPUNIT_ASSERT(std::isinf(res));
622 // #i97605
623 CPPUNIT_ASSERT_DOUBLES_EQUAL(691.67568924815798, rtl::math::asinh(1.23e+300), 1e-15);
624 CPPUNIT_ASSERT_DOUBLES_EQUAL(1.0350378961923076, rtl::math::asinh(1.23), 1e-16);
625 CPPUNIT_ASSERT_DOUBLES_EQUAL(1.23e-300, rtl::math::asinh(1.23e-300), 1e-303);
627 // asinh is an odd function
628 CPPUNIT_ASSERT_EQUAL(-rtl::math::asinh(1.23e+300), rtl::math::asinh(-1.23e+300));
629 CPPUNIT_ASSERT_EQUAL(-rtl::math::asinh(1.23), rtl::math::asinh(-1.23));
630 CPPUNIT_ASSERT_EQUAL(-rtl::math::asinh(1.23e-300), rtl::math::asinh(-1.23e-300));
633 void test_atanh() {
634 double res;
636 res = rtl::math::atanh(-2.0); // NaN
637 CPPUNIT_ASSERT(std::isnan(res));
639 res = rtl::math::atanh(-1.0); // -Inf
640 CPPUNIT_ASSERT(std::signbit(res));
641 CPPUNIT_ASSERT(std::isinf(res));
643 CPPUNIT_ASSERT_EQUAL(0.0, rtl::math::atanh(0.0));
645 res = rtl::math::atanh(1.0); // +Inf
646 CPPUNIT_ASSERT(!std::signbit(res));
647 CPPUNIT_ASSERT(std::isinf(res));
649 res = rtl::math::atanh(2.0); // NaN
650 CPPUNIT_ASSERT(std::isnan(res));
653 void test_payloadNaN() {
654 // Test that a quiet NaN payload is propagated and behaves as we
655 // expect. Ideally that could be done with a constexpr in
656 // sal/rtl/math.cxx to fail already during compile time instead of make
657 // check, but..
658 // See
659 // https://grouper.ieee.org/groups/msc/ANSI_IEEE-Std-754-2019/background/nan-propagation.pdf
660 double fVal1 = std::numeric_limits<double>::quiet_NaN();
661 reinterpret_cast<sal_math_Double*>(&fVal1)->nan_parts.fraction_lo = 0xbeef;
662 const double fVal2 = 0 + fVal1;
663 CPPUNIT_ASSERT(std::isnan(fVal2));
664 CPPUNIT_ASSERT_EQUAL_MESSAGE("Your platform does not support propagation of NaN payloads.",
665 static_cast<sal_uInt32>(0xbeef),
666 static_cast<sal_uInt32>(reinterpret_cast<const sal_math_Double*>(&fVal2)->nan_parts.fraction_lo));
667 reinterpret_cast<sal_math_Double*>(&fVal1)->nan_parts.fraction_lo = 0xdead;
668 const double fVal3 = fVal1 + fVal2;
669 // Result is one of the payloaded NaNs but the standard does not
670 // specify which.
671 CPPUNIT_ASSERT_MESSAGE("Your platform does not support propagation of two combined NaN payloads.",
672 0xbeef == reinterpret_cast<const sal_math_Double*>(&fVal3)->nan_parts.fraction_lo ||
673 0xdead == reinterpret_cast<const sal_math_Double*>(&fVal3)->nan_parts.fraction_lo);
676 CPPUNIT_TEST_SUITE(Test);
677 CPPUNIT_TEST(test_stringToDouble_good);
678 CPPUNIT_TEST(test_stringToDouble_bad);
679 CPPUNIT_TEST(test_stringToDouble_exponent_without_digit);
680 CPPUNIT_TEST(test_round);
681 CPPUNIT_TEST(test_doubleToString);
682 CPPUNIT_TEST(test_erf);
683 CPPUNIT_TEST(test_erfc);
684 CPPUNIT_TEST(test_expm1);
685 CPPUNIT_TEST(test_log1p);
686 CPPUNIT_TEST(test_approx);
687 CPPUNIT_TEST(test_acosh);
688 CPPUNIT_TEST(test_asinh);
689 CPPUNIT_TEST(test_atanh);
690 CPPUNIT_TEST(test_payloadNaN);
691 CPPUNIT_TEST_SUITE_END();
694 CPPUNIT_TEST_SUITE_REGISTRATION(Test);
698 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */