From b45dec9c324a068a4c1dcf878bd3cc4c627cc4da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Thu, 10 Nov 2022 21:08:54 +0100 Subject: [PATCH 1/2] log: add a separate path for ratios While not necessarily a bug, it is convenient to not overflow on very small ratios. When feasible instead of converting to float, we compute log of the number and the denominator and then return their difference. c.f https://mailman.common-lisp.net/pipermail/ecl-devel/2022-July/011628.html --- src/c/numbers/log.d | 19 ++++++++++++++++++- src/h/impl/math_dispatch.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/c/numbers/log.d b/src/c/numbers/log.d index dd1e0ec95..68e939a3b 100644 --- a/src/c/numbers/log.d +++ b/src/c/numbers/log.d @@ -17,6 +17,7 @@ #include #include #include +#include #include #pragma STDC FENV_ACCESS ON @@ -88,6 +89,22 @@ ecl_log1_simple(cl_object x) return ecl_make_single_float(logf(ecl_to_float(x))); } +static cl_object +ecl_log1_ratio(cl_object x) +{ + cl_object num = x->ratio.num; + cl_object den = x->ratio.den; + cl_index lnum = ecl_integer_length(num); + cl_index lden = ecl_integer_length(den); + if ((lnum > lden) ? (lnum - lden >= FLT_MAX_EXP) : (lden - lnum >= -FLT_MIN_EXP)) { + cl_object numlog = ecl_log1(num); + cl_object denlog = ecl_log1(den); + return ecl_minus(numlog, denlog); + } else { + return ecl_log1_simple(x); + } +} + static cl_object ecl_log1_single_float(cl_object x) { @@ -182,7 +199,7 @@ ecl_log1_clfloat(cl_object x) #endif MATH_DEF_DISPATCH1(log1, @[log], @[number], - ecl_log1_simple, ecl_log1_bignum, ecl_log1_simple, + ecl_log1_simple, ecl_log1_bignum, ecl_log1_ratio, ecl_log1_single_float, ecl_log1_double_float, ecl_log1_long_float, ecl_log1_complex, ecl_log1_csfloat, ecl_log1_cdfloat, ecl_log1_clfloat); diff --git a/src/h/impl/math_dispatch.h b/src/h/impl/math_dispatch.h index 6acf3cffe..23f900206 100644 --- a/src/h/impl/math_dispatch.h +++ b/src/h/impl/math_dispatch.h @@ -54,6 +54,7 @@ typedef cl_object (*math_one_arg_fn)(cl_object); } \ return name##dispatch[t](arg); \ } + #define MATH_DEF_DISPATCH1(name,id,type,fix,big,ratio, \ single_float,double_float,long_float, \ complex,csfloat,cdfloat,clfloat) \ From 06e553157c0260db4db2303e0ddb2e382f47689c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Kochma=C5=84ski?= Date: Thu, 10 Nov 2022 21:12:27 +0100 Subject: [PATCH 2/2] tests: add a regression test for (log small-ratio) --- src/tests/normal-tests/mixed.lsp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tests/normal-tests/mixed.lsp b/src/tests/normal-tests/mixed.lsp index 0d7522e39..c3f82c51b 100644 --- a/src/tests/normal-tests/mixed.lsp +++ b/src/tests/normal-tests/mixed.lsp @@ -429,3 +429,8 @@ (let ((vector (si:make-vector t 10 t nil nil nil))) (si:adjust-vector vector 20) (is (= 20 (array-total-size vector))))) + +;;; Created: 2022-11-10 +;;; Contains: a test for a logarithm of a very small ratio +(test mix.0023.log-small-ratio + (finishes (log (/ 1 6319748715279270675921934218987893281199411530039296))))