1

I am working on a library for multiple precision floating point numbers. I implemented computation of natural logarithm as follows:

  1. Factoring of decimal powers first:

$$ln(m*10^e) = \ln(m*10^{(1-n)}) + (e - 1 + n)*\ln(10)$$

here m is mantissa, n is the number of decimal position in m, e is exponent part of a number.

  1. Factoring $m*10^{(1-n)}$ with dividing by 2, so after several divisions it represents a number laying within range [1, 2).

  2. Use series based on inverse hyperbolic tangent https://en.wikipedia.org/wiki/Logarithm#Inverse_hyperbolic_tangent

It does the calculation, but I have two problems:

  • it seems to be slow.
  • it seems like it lacks precision.

To mitigate the second problem I used increased mantissa, but there is still discrepancy of about 3 least significant decimal digits (I check the results by inverse calculation, i.e $e^{ln(x)}$).

How could I improve this algorithm with regard to above mentioned problems?

  • Why are you using base $10$ at all? Surely your floating point numbers use base $2$? – TonyK Jun 12 '22 at 11:39
  • @TonyK I initially was designing it for my dbms project. And in dbms numeric types usually have length specified in decimal digits, e.g. https://doxygen.postgresql.org/pgtypes__numeric_8h_source.html#l00029 – stencillogic Jun 12 '22 at 13:20
  • Well that's the most important step you could take to improve performance -- switch to binary (by which I suppose I mean base $2^n$ for some $n$, say $16$ or $32$). – TonyK Jun 12 '22 at 13:24
  • @TonyK Thank you for your suggestion. Rewriting is a time consuming procedure. But as workaround for the time being I looked at the implementation of ln in postgresql. It uses similar approach, but for step 3 the range is more narrow. So, probably the key is more narrow range, and will try this approach first – stencillogic Jun 12 '22 at 13:55
  • For medium precision (say, 100 decimal digits), computation via artanh as core approximation should be fine. For good performance, original argument $x$ needs to be reduced to a number very close to $1$ and multiplicatively symmetric around it. Start with (f, e) = frexp10 (x), then $f$ is in $[0.1, 1)$. If $f \lt \sqrt{0.1}$, set $e:=e-1$, $f:=10*f$. Now $f$ in $[\sqrt{0.1},\sqrt{10}]$. We can reduce $f$ further by applying square root $k$ times, using $\log(f) = 2^{k}\log(x^{2^{-k}})$. As argument for the artanh core approximation we then compute $s:=\frac{f-1}{f+1}$. – njuffa Jun 12 '22 at 19:27
  • Why do you need the first step? – uranix Jun 13 '22 at 07:44

0 Answers0