1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-21 19:20:21 +02:00

Improvements to log' and log10'

* libguile/numbers.c (log_of_shifted_double, log_of_exact_integer,
  log_of_exact_integer_with_size, log_of_fraction): New internal static
  functions used by scm_log and scm_log10.

  (scm_log, scm_log10): Robustly handle large integers, large and small
  fractions, and fractions close to 1.  Previously, computing logarithms
  of fractions close to 1 yielded grossly inaccurate results, and the
  other cases yielded infinities even though the answer could easily fit
  in a double.  (log -0.0) now returns -inf.0+<PI>i, where previously it
  returned -inf.0.  (log 0) now throws a numerical overflow exception,
  where previously it returned -inf.0.  (log 0.0) still returns -inf.0.
  Analogous changes made to `log10'.

* test-suite/tests/numbers.test (log, log10): Add tests.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Mark H Weaver 2011-02-15 10:37:03 -05:00 committed by Ludovic Courtès
parent c05696aa94
commit a5f6b751be
2 changed files with 150 additions and 34 deletions

View file

@ -4323,14 +4323,36 @@
(log))
(pass-if-exception "two args" exception:wrong-num-args
(log 123 456))
(pass-if-exception "(log 0)" exception:numerical-overflow
(log 0))
(pass-if (negative-infinity? (log 0)))
(pass-if (negative-infinity? (log 0.0)))
(pass-if (eqv? 0.0 (log 1)))
(pass-if (eqv? 0.0 (log 1.0)))
(pass-if (eqv-loosely? 1.0 (log const-e)))
(pass-if (eqv-loosely? 2.0 (log const-e^2)))
(pass-if (eqv-loosely? -1.0 (log const-1/e)))
(pass-if (test-eqv? -inf.0 (log 0.0)))
(pass-if (test-eqv? +inf.0 (log +inf.0)))
(pass-if (test-eqv? -inf.0+3.14159265358979i (log -0.0)))
(pass-if (test-eqv? +inf.0+3.14159265358979i (log -inf.0)))
(pass-if (test-eqv? 0.0 (log 1 )))
(pass-if (test-eqv? 0.0 (log 1.0)))
(pass-if (test-eqv? 1.0 (log const-e)))
(pass-if (test-eqv? 2.0 (log const-e^2)))
(pass-if (test-eqv? -1.0 (log const-1/e)))
(pass-if (test-eqv? -1.0+3.14159265358979i (log (- const-1/e))))
(pass-if (test-eqv? 2.30258509299405 (log 10)))
(pass-if (test-eqv? 2.30258509299405+3.14159265358979i (log -10)))
(pass-if (test-eqv? 1.0+0.0i (log (+ const-e +0.0i))))
(pass-if (test-eqv? 1.0-0.0i (log (+ const-e -0.0i))))
(pass-if (eqv-loosely? 230258.509299405 (log (expt 10 100000))))
(pass-if (eqv-loosely? -230258.509299405 (log (expt 10 -100000))))
(pass-if (eqv-loosely? 230257.410687116 (log (/ (expt 10 100000) 3))))
(pass-if (eqv-loosely? 230258.509299405+3.14159265358979i
(log (- (expt 10 100000)))))
(pass-if (eqv-loosely? -230258.509299405+3.14159265358979i
(log (- (expt 10 -100000)))))
(pass-if (eqv-loosely? 230257.410687116+3.14159265358979i
(log (- (/ (expt 10 100000) 3)))))
(pass-if (test-eqv? 3.05493636349961e-151
(log (/ (1+ (expt 2 500)) (expt 2 500)))))
(pass-if (eqv-loosely? 1.0+1.57079i (log 0+2.71828i)))
(pass-if (eqv-loosely? 1.0-1.57079i (log 0-2.71828i)))
@ -4350,20 +4372,42 @@
(log10))
(pass-if-exception "two args" exception:wrong-num-args
(log10 123 456))
(pass-if-exception "(log10 0)" exception:numerical-overflow
(log10 0))
(pass-if (negative-infinity? (log10 0)))
(pass-if (negative-infinity? (log10 0.0)))
(pass-if (eqv? 0.0 (log10 1)))
(pass-if (eqv? 0.0 (log10 1.0)))
(pass-if (eqv-loosely? 1.0 (log10 10.0)))
(pass-if (eqv-loosely? 2.0 (log10 100.0)))
(pass-if (eqv-loosely? -1.0 (log10 0.1)))
(pass-if (test-eqv? -inf.0 (log10 0.0)))
(pass-if (test-eqv? +inf.0 (log10 +inf.0)))
(pass-if (test-eqv? -inf.0+1.36437635384184i (log10 -0.0)))
(pass-if (test-eqv? +inf.0+1.36437635384184i (log10 -inf.0)))
(pass-if (test-eqv? 0.0 (log10 1 )))
(pass-if (test-eqv? 0.0 (log10 1.0)))
(pass-if (test-eqv? 1.0 (log10 10 )))
(pass-if (test-eqv? 1.0 (log10 10.0)))
(pass-if (test-eqv? 2.0 (log10 100.0)))
(pass-if (test-eqv? -1.0 (log10 0.1)))
(pass-if (test-eqv? -1.0+1.36437635384184i (log10 -0.1)))
(pass-if (test-eqv? 1.0+1.36437635384184i (log10 -10 )))
(pass-if (test-eqv? 1.0+0.0i (log10 10.0+0.0i)))
(pass-if (test-eqv? 1.0-0.0i (log10 10.0-0.0i)))
(pass-if (eqv-loosely? 100000.0 (log10 (expt 10 100000))))
(pass-if (eqv-loosely? -100000.0 (log10 (expt 10 -100000))))
(pass-if (eqv-loosely? 99999.5228787453 (log10 (/ (expt 10 100000) 3))))
(pass-if (eqv-loosely? 100000.0+1.36437635384184i
(log10 (- (expt 10 100000)))))
(pass-if (eqv-loosely? -100000.0+1.36437635384184i
(log10 (- (expt 10 -100000)))))
(pass-if (eqv-loosely? 99999.5228787453+1.36437635384184i
(log10 (- (/ (expt 10 100000) 3)))))
(pass-if (test-eqv? 1.32674200523347e-151
(log10 (/ (1+ (expt 2 500)) (expt 2 500)))))
(pass-if (eqv-loosely? 1.0+0.68218i (log10 0+10.0i)))
(pass-if (eqv-loosely? 1.0-0.68218i (log10 0-10.0i)))
(pass-if (eqv-loosely? 0.0+1.36437i (log10 -1)))
(pass-if (eqv-loosely? 1.0+1.36437i (log10 -10)))
(pass-if (eqv-loosely? 0.0+1.36437i (log10 -1)))
(pass-if (eqv-loosely? 1.0+1.36437i (log10 -10)))
(pass-if (eqv-loosely? 2.0+1.36437i (log10 -100))))
;;;