annotate lib/log2f.c @ 17426:90f3d53e01f5

sig2str: port to C++ * lib/sig2str.h (sig2str, str2sig): Declare as extern "C". Reported by Daniel J Sebald in <http://lists.gnu.org/archive/html/bug-gnulib/2013-06/msg00000.html>.
author Paul Eggert <eggert@cs.ucla.edu>
date Sun, 02 Jun 2013 11:52:41 -0700
parents e542fd46ad6f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
16678
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
1 /* Base 2 logarithm.
17249
e542fd46ad6f maint: update all copyright year number ranges
Eric Blake <eblake@redhat.com>
parents: 16678
diff changeset
2 Copyright (C) 2012-2013 Free Software Foundation, Inc.
16678
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
3
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
4 This program is free software: you can redistribute it and/or modify
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
5 it under the terms of the GNU General Public License as published by
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
6 the Free Software Foundation; either version 3 of the License, or
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
7 (at your option) any later version.
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
8
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
9 This program is distributed in the hope that it will be useful,
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
12 GNU General Public License for more details.
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
13
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
14 You should have received a copy of the GNU General Public License
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
16
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
17 #include <config.h>
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
18
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
19 /* Specification. */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
20 #include <math.h>
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
21
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
22 #if HAVE_LOG2
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
23
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
24 float
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
25 log2f (float x)
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
26 {
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
27 return (float) log2 ((double) x);
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
28 }
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
29
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
30 #else
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
31
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
32 /* Best possible approximation of log(2) as a 'float'. */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
33 #define LOG2 0.693147180559945309417232121458176568075f
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
34
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
35 /* Best possible approximation of 1/log(2) as a 'float'. */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
36 #define LOG2_INVERSE 1.44269504088896340735992468100189213743f
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
37
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
38 /* sqrt(0.5). */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
39 #define SQRT_HALF 0.707106781186547524400844362104849039284f
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
40
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
41 float
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
42 log2f (float x)
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
43 {
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
44 if (isnanf (x))
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
45 return x;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
46
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
47 if (x <= 0.0f)
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
48 {
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
49 if (x == 0.0f)
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
50 /* Return -Infinity. */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
51 return - HUGE_VALF;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
52 else
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
53 {
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
54 /* Return NaN. */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
55 #if defined _MSC_VER
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
56 static float zero;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
57 return zero / zero;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
58 #else
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
59 return 0.0f / 0.0f;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
60 #endif
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
61 }
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
62 }
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
63
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
64 /* Decompose x into
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
65 x = 2^e * y
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
66 where
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
67 e is an integer,
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
68 1/2 < y < 2.
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
69 Then log2(x) = e + log2(y) = e + log(y)/log(2). */
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
70 {
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
71 int e;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
72 float y;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
73
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
74 y = frexpf (x, &e);
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
75 if (y < SQRT_HALF)
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
76 {
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
77 y = 2.0f * y;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
78 e = e - 1;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
79 }
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
80
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
81 return (float) e + logf (y) * LOG2_INVERSE;
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
82 }
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
83 }
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
84
2f6973f75a06 New module 'log2f'.
Bruno Haible <bruno@clisp.org>
parents:
diff changeset
85 #endif