time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

commit 6e22e78d4fd70b9e38542d7cd8c2ba931a571801
parent 7e2d2b95a17723ecb886d8acc1951fa32aebb96b
Author: NunoSempere <nuno.sempere@protonmail.com>
Date:   Sat, 20 May 2023 22:38:38 -0400

add cool implementation of the logarithm

Diffstat:
Mwip/nim/samples | 0
Mwip/nim/samples.nim | 43+++++++++++++++++++++++++++++--------------
2 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/wip/nim/samples b/wip/nim/samples Binary files differ. diff --git a/wip/nim/samples.nim b/wip/nim/samples.nim @@ -22,11 +22,24 @@ proc sine(x: float): float = acc = acc + taylor return acc -# Helpers for calculating the log function +## Log function + +## Old implementation using Taylor expansion +proc log_slow(x: float): float = + var y = x - 1 + let n = 100000000 + var acc = 0.0 + for i in 1..n: + let taylor = pow(-1.0, float(i+1)) * pow(y, i.float) / i.float + acc = acc + taylor + return acc + +## New implementation +## <https://en.wikipedia.org/wiki/Natural_logarithm#High_precision> ## Arithmetic-geomtric mean proc ag(x: float, y: float): float = - let n = 100 + let n = 128 # just some high number var a = (x + y)/2.0 var b = sqrt(x * y) for i in 0..n: @@ -35,26 +48,28 @@ proc ag(x: float, y: float): float = b = sqrt(b*temp) return a -## Find m such that x * 2^m > 2^100 - -proc log_slow(x: float): float = - # See: <https://en.wikipedia.org/wiki/Natural_logarithm#High_precision> - var y = x - 1 - let n = 100000000 - var acc = 0.0 - for i in 1..n: - let taylor = pow(-1.0, float(i+1)) * pow(y, i.float) / i.float - acc = acc + taylor - return acc +## Find m such that x * 2^m > 2^precision/2 +proc find_m(x:float): float = + var m = 0.0; + let precision = 64 # bits + let c = pow(2.0, precision.float / 2.0) + while x * pow(2.0, m) < c: + m = m + 1 + return m proc log(x: float): float = - return 1 + let m = find_m(x) + let s = x * pow(2.0, m) + let ln2 = 0.6931471805599453 + return ( PI / (2.0 * ag(1, 4.0/s)) ) - m * ln2 ## Test these functions echo factorial(5) echo sine(1.0) echo log(1.0) echo log(2.0) +echo log(3.0) +echo pow(2.0, 32.float) ## Distribution functions proc normal(): float =