Skip to content

Commit e4c3c7d

Browse files
committed
Simplify log and add 128-bit coefs/tests
1 parent 8cab9e6 commit e4c3c7d

File tree

3 files changed

+186
-36
lines changed

3 files changed

+186
-36
lines changed

include/boost/decimal/detail/cmath/impl/log_impl.hpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ struct log_table_imp
2727
private:
2828
using d32_coeffs_t = std::array<decimal32, 8>;
2929
using d64_coeffs_t = std::array<decimal64, 11>;
30-
using d128_coeffs_t = std::array<decimal128, 17>;
30+
using d128_coeffs_t = std::array<decimal128, 21>;
3131

3232
public:
3333
static constexpr d32_coeffs_t d32_coeffs =
@@ -63,25 +63,29 @@ struct log_table_imp
6363

6464
static constexpr d128_coeffs_t d128_coeffs =
6565
{{
66-
// Series[Cosh[x], {x, 0, 34}]
67-
// (1), // * 1
68-
::boost::decimal::decimal128 { 5, -1 }, // * x^2
69-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(225875452601146), UINT64_C(13965751134118914724) }, -35 }, // * x^4
70-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(75291817533715), UINT64_C(10804165069276155440) }, -36 }, // * x^6
71-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(134449674167349), UINT64_C(4799281565792772746) }, -38 }, // * x^8
72-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(149388526852610), UINT64_C(5332535073103080820) }, -40 }, // * x^10
73-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(113173126403492), UINT64_C(11865690723015477068) }, -42 }, // * x^12
74-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(62183036485435), UINT64_C(9560282387433155251) }, -44 }, // * x^14
75-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(259095985355981), UINT64_C(6015479145837302244) }, -47 }, // * x^16
76-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(84671890639209), UINT64_C(10767230553416093986) }, -49 }, // * x^18
77-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(222820764840025), UINT64_C(4062785569898205740) }, -52 }, // * x^20
78-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(482296027792262), UINT64_C(7037075391028107068) }, -55 }, // * x^22
79-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(87372468802946), UINT64_C(1542176615384940434) }, -57 }, // * x^24
80-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(134419182773763), UINT64_C(3791559721646796942) }, -60 }, // * x^26
81-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(177803151817147), UINT64_C(1794430560736952558) }, -63 }, // * x^28
82-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(204371438870284), UINT64_C(366311534299067156) }, -66 }, // * x^30
83-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(206019595635366), UINT64_C(17625897212400736954) }, -69 }, // * x^32
84-
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(183618177928134), UINT64_C(9987905770721758456) }, -72 }, // * x^34
66+
// Series[Log[(1 + (z/2))/(1 - (z/2))], {z, 0, 43}]
67+
// (1), // * z
68+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(451750905202293), UINT64_C(9484758194528277842) }, -35 }, // * z^3
69+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(67762635780344), UINT64_C(500376525493764096) }, -35 }, // * z^5
70+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(121004706750614), UINT64_C(6164027816584450626) }, -36 }, // * z^7
71+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(235286929792861), UINT64_C(3787056721709964394) }, -37 }, // * z^9
72+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(481268720030852), UINT64_C(8584740752302634068) }, -38 }, // * z^11
73+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(101806844621911), UINT64_C(1816002851448634124) }, -38 }, // * z^13
74+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(220581496680807), UINT64_C(7009130190423632548) }, -39 }, // * z^15
75+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(486576830913545), UINT64_C(12748560115094843630) }, -40 }, // * z^17
76+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(108839554283293), UINT64_C(2123490654414259032) }, -40 }, // * z^19
77+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(246184706116972), UINT64_C(9634423737622849438) }, -41 }, // * z^21
78+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(56194335091917), UINT64_C(11823550152479764302) }, -41 }, // * z^23
79+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(129246970711410), UINT64_C(10592095684364861440) }, -42 }, // * z^25
80+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(299182802572709), UINT64_C(12220910627630811506) }, -43 }, // * z^27
81+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(69637376460889), UINT64_C(5865971761607874066) }, -43 }, // * z^29
82+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(162861606239176), UINT64_C(11636108014793143194) }, -44 }, // * z^31
83+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(382478014652611), UINT64_C(14470401740943906374) }, -45 }, // * z^33
84+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(90155532025258), UINT64_C(9076666090147568782) }, -45 }, // * z^35
85+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(213205650059732), UINT64_C(16978042870933143358) }, -46 }, // * z^37
86+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(505680067449366), UINT64_C(9996854995997550184) }, -47 }, // * z^39
87+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(120253186771495), UINT64_C(12950434681540257980) }, -47 }, // * z^41
88+
::boost::decimal::decimal128 { boost::decimal::detail::uint128 { UINT64_C(286650038234379), UINT64_C(5345076336561816786) }, -48 }, // * z^43
8589
}};
8690
};
8791

include/boost/decimal/detail/cmath/log.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Copyright 2023 Matt Borland
2-
// Copyright 2023 Christopher Kormanyos
1+
// Copyright 2023 - 2024 Matt Borland
2+
// Copyright 2023 - 2024 Christopher Kormanyos
33
// Distributed under the Boost Software License, Version 1.0.
44
// https://www.boost.org/LICENSE_1_0.txt
55

test/test_log.cpp

Lines changed: 160 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,31 @@ namespace local
5656

5757
auto result_is_ok = bool { };
5858

59+
NumericType delta { };
60+
5961
if(b == static_cast<NumericType>(0))
6062
{
61-
result_is_ok = (fabs(a - b) < tol);
63+
delta = fabs(a - b); // LCOV_EXCL_LINE
64+
65+
result_is_ok = (delta < tol); // LCOV_EXCL_LINE
6266
}
6367
else
6468
{
65-
const auto delta = fabs(1 - (a / b));
69+
delta = fabs(1 - (a / b));
6670

6771
result_is_ok = (delta < tol);
6872
}
6973

74+
// LCOV_EXCL_START
75+
if (!result_is_ok)
76+
{
77+
std::cerr << std::setprecision(std::numeric_limits<NumericType>::digits10) << "a: " << a
78+
<< "\nb: " << b
79+
<< "\ndelta: " << delta
80+
<< "\ntol: " << tol << std::endl;
81+
}
82+
// LCOV_EXCL_STOP
83+
7084
return result_is_ok;
7185
}
7286

@@ -93,7 +107,7 @@ namespace local
93107
auto trials = static_cast<std::uint32_t>(UINT8_C(0));
94108

95109
#if !defined(BOOST_DECIMAL_REDUCE_TEST_DEPTH)
96-
constexpr auto count = (sizeof(decimal_type) == static_cast<std::size_t>(UINT8_C(4))) ? static_cast<std::uint32_t>(UINT32_C(0x400)) : static_cast<std::uint32_t>(UINT32_C(0x40));
110+
constexpr auto count = (sizeof(decimal_type) == static_cast<std::size_t>(UINT8_C(4))) ? static_cast<std::uint32_t>(UINT32_C(0x200)) : static_cast<std::uint32_t>(UINT32_C(0x40));
97111
#else
98112
constexpr auto count = (sizeof(decimal_type) == static_cast<std::size_t>(UINT8_C(4))) ? static_cast<std::uint32_t>(UINT32_C(0x40)) : static_cast<std::uint32_t>(UINT32_C(0x4));
99113
#endif
@@ -114,13 +128,13 @@ namespace local
114128

115129
if(!result_log_is_ok)
116130
{
117-
// LCOV_EXCL_START
118-
std::cout << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << x_flt << std::endl;
119-
std::cout << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_flt << std::endl;
120-
std::cout << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_dec << std::endl;
131+
// LCOV_EXCL_START
132+
std::cerr << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << x_flt << std::endl;
133+
std::cerr << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_flt << std::endl;
134+
std::cerr << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_dec << std::endl;
121135

122136
break;
123-
// LCOV_EXCL_STOP
137+
// LCOV_EXCL_STOP
124138
}
125139
}
126140

@@ -155,13 +169,13 @@ namespace local
155169

156170
if(!result_log_is_ok)
157171
{
158-
// LCOV_EXCL_START
159-
std::cout << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << x_flt << std::endl;
160-
std::cout << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_flt << std::endl;
161-
std::cout << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_dec << std::endl;
172+
// LCOV_EXCL_START
173+
std::cerr << "x_flt : " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << x_flt << std::endl;
174+
std::cerr << "val_flt: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_flt << std::endl;
175+
std::cerr << "val_dec: " << std::scientific << std::setprecision(std::numeric_limits<float_type>::digits10) << val_dec << std::endl;
162176

163177
break;
164-
// LCOV_EXCL_START
178+
// LCOV_EXCL_START
165179
}
166180
}
167181

@@ -312,7 +326,123 @@ namespace local
312326

313327
return result_is_ok;
314328
}
315-
}
329+
330+
auto test_log_64(const int tol_factor) -> bool
331+
{
332+
using decimal_type = boost::decimal::decimal64;
333+
334+
using val_ctrl_array_type = std::array<double, 28U>;
335+
336+
const val_ctrl_array_type ctrl_values =
337+
{{
338+
// Table[N[Log[111 10^n], 17], {n, -3, 24, 1}]
339+
-2.1982250776698029, 0.10436001532424277, 2.4069451083182885,
340+
4.7095302013123341, 7.0121152943063798, 9.3147003873004255,
341+
11.617285480294471, 13.919870573288517, 16.222455666282563,
342+
18.525040759276608, 20.827625852270654, 23.130210945264700,
343+
25.432796038258745, 27.735381131252791, 30.037966224246837,
344+
32.340551317240882, 34.643136410234928, 36.945721503228974,
345+
39.248306596223019, 41.550891689217065, 43.853476782211111,
346+
46.156061875205156, 48.458646968199202, 50.761232061193248,
347+
53.063817154187294, 55.366402247181339, 57.668987340175385,
348+
59.971572433169431
349+
}};
350+
351+
std::array<decimal_type, std::tuple_size<val_ctrl_array_type>::value> log_values { };
352+
353+
int nx { -3 };
354+
355+
bool result_is_ok { true };
356+
357+
const decimal_type my_tol { std::numeric_limits<decimal_type>::epsilon() * static_cast<decimal_type>(tol_factor) };
358+
359+
for(auto i = static_cast<std::size_t>(UINT8_C(0)); i < std::tuple_size<val_ctrl_array_type>::value; ++i)
360+
{
361+
// Table[N[Log[111 10^n], 17], {n, -3, 24, 1}]
362+
363+
const decimal_type x_arg { 111, nx };
364+
365+
log_values[i] = log(x_arg);
366+
367+
++nx;
368+
369+
const auto result_log_is_ok = is_close_fraction(log_values[i], decimal_type(ctrl_values[i]), my_tol);
370+
371+
result_is_ok = (result_log_is_ok && result_is_ok);
372+
}
373+
374+
return result_is_ok;
375+
}
376+
377+
auto test_log_128(const int tol_factor) -> bool
378+
{
379+
using decimal_type = boost::decimal::decimal128;
380+
381+
using str_ctrl_array_type = std::array<const char*, 28U>;
382+
383+
const str_ctrl_array_type ctrl_strings =
384+
{{
385+
// Table[N[Log[111 10^n], 36], {n, -3, 24, 1}]
386+
"-2.19822507766980291629063345609911975",
387+
"0.104360015324242767727357998585244453",
388+
"2.40694510831828845174534945326960866",
389+
"4.70953020131233413576334090795397287",
390+
"7.01211529430637981978133236263833708",
391+
"9.31470038730042550379932381732270128",
392+
"11.6172854802944711878173152720070655",
393+
"13.9198705732885168718353067266914297",
394+
"16.2224556662825625558532981813757939",
395+
"18.5250407592766082398712896360601581",
396+
"20.8276258522706539238892810907445223",
397+
"23.1302109452646996079072725454288865",
398+
"25.4327960382587452919252640001132507",
399+
"27.7353811312527909759432554547976149",
400+
"30.0379662242468366599612469094819792",
401+
"32.3405513172408823439792383641663434",
402+
"34.6431364102349280279972298188507076",
403+
"36.9457215032289737120152212735350718",
404+
"39.2483065962230193960332127282194360",
405+
"41.5508916892170650800512041829038002",
406+
"43.8534767822111107640691956375881644",
407+
"46.1560618752051564480871870922725286",
408+
"48.4586469681992021321051785469568928",
409+
"50.7612320611932478161231700016412570",
410+
"53.0638171541872935001411614563256212",
411+
"55.3664022471813391841591529110099854",
412+
"57.6689873401753848681771443656943496",
413+
"59.9715724331694305521951358203787139",
414+
}};
415+
416+
std::array<decimal_type, std::tuple_size<str_ctrl_array_type>::value> log_values { };
417+
std::array<decimal_type, std::tuple_size<str_ctrl_array_type>::value> ctrl_values { };
418+
419+
int nx { -3 };
420+
421+
bool result_is_ok { true };
422+
423+
const decimal_type my_tol { std::numeric_limits<decimal_type>::epsilon() * static_cast<decimal_type>(tol_factor) };
424+
425+
for(auto i = static_cast<std::size_t>(UINT8_C(0)); i < std::tuple_size<str_ctrl_array_type>::value; ++i)
426+
{
427+
const decimal_type x_arg { 111, nx };
428+
429+
++nx;
430+
431+
log_values[i] = log(x_arg);
432+
433+
static_cast<void>
434+
(
435+
from_chars(ctrl_strings[i], ctrl_strings[i] + std::strlen(ctrl_strings[i]), ctrl_values[i])
436+
);
437+
438+
const auto result_log_is_ok = is_close_fraction(log_values[i], ctrl_values[i], my_tol);
439+
440+
result_is_ok = (result_log_is_ok && result_is_ok);
441+
}
442+
443+
return result_is_ok;
444+
}
445+
} // namespace local
316446

317447
auto main() -> int
318448
{
@@ -340,6 +470,22 @@ auto main() -> int
340470
result_is_ok = (test_log_is_ok && test_log_between_1_and_2_is_ok && test_log_edge_is_ok && result_is_ok);
341471
}
342472

473+
{
474+
const auto result_pos64_is_ok = local::test_log_64(512);
475+
476+
BOOST_TEST(result_pos64_is_ok);
477+
478+
result_is_ok = (result_pos64_is_ok && result_is_ok);
479+
}
480+
481+
{
482+
const auto result_pos128_is_ok = local::test_log_128(1'400'000);
483+
484+
BOOST_TEST(result_pos128_is_ok);
485+
486+
result_is_ok = (result_pos128_is_ok && result_is_ok);
487+
}
488+
343489
result_is_ok = ((boost::report_errors() == 0) && result_is_ok);
344490

345491
return (result_is_ok ? 0 : -1);

0 commit comments

Comments
 (0)