Mercurial > hg > octave-shane > gnulib-hg
annotate lib/signbitl.c @ 11506:d800366aa3fe
Avoid link error when creating a namespace clean library.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sat, 25 Apr 2009 17:22:50 +0200 |
parents | bbbbbf4cd1c5 |
children | 0b09102d516e |
rev | line source |
---|---|
8652 | 1 /* signbit() macro: Determine the sign bit of a floating-point number. |
11506
d800366aa3fe
Avoid link error when creating a namespace clean library.
Bruno Haible <bruno@clisp.org>
parents:
9309
diff
changeset
|
2 Copyright (C) 2007, 2009 Free Software Foundation, Inc. |
8652 | 3 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8659
diff
changeset
|
4 This program is free software: you can redistribute it and/or modify |
8652 | 5 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8659
diff
changeset
|
6 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8659
diff
changeset
|
7 (at your option) any later version. |
8652 | 8 |
9 This program is distributed in the hope that it will be useful, | |
10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 GNU General Public License for more details. | |
13 | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8659
diff
changeset
|
14 You should have received a copy of the GNU General Public License |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
8659
diff
changeset
|
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
8652 | 16 |
17 #include <config.h> | |
18 | |
19 /* Specification. */ | |
20 #include <math.h> | |
21 | |
22 #include <string.h> | |
23 #include "isnanl-nolibm.h" | |
24 #include "float+.h" | |
25 | |
26 int | |
27 gl_signbitl (long double arg) | |
28 { | |
29 #if defined LDBL_SIGNBIT_WORD && defined LDBL_SIGNBIT_BIT | |
8659
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
30 /* The use of a union to extract the bits of the representation of a |
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
31 'long double' is safe in practice, despite of the "aliasing rules" of |
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
32 C99, because the GCC docs say |
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
33 "Even with '-fstrict-aliasing', type-punning is allowed, provided the |
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
34 memory is accessed through the union type." |
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
35 and similarly for other compilers. */ |
8652 | 36 # define NWORDS \ |
37 ((sizeof (long double) + sizeof (unsigned int) - 1) / sizeof (unsigned int)) | |
38 union { long double value; unsigned int word[NWORDS]; } m; | |
39 m.value = arg; | |
40 return (m.word[LDBL_SIGNBIT_WORD] >> LDBL_SIGNBIT_BIT) & 1; | |
8659
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
41 #elif HAVE_COPYSIGNL_IN_LIBC |
d6d05661430a
Use copysign when implementing signbit, if the libc has it already.
Bruno Haible <bruno@clisp.org>
parents:
8652
diff
changeset
|
42 return copysignl (1.0L, arg) < 0; |
8652 | 43 #else |
44 /* This does not do the right thing for NaN, but this is irrelevant for | |
45 most use cases. */ | |
46 if (isnanl (arg)) | |
47 return 0; | |
48 if (arg < 0.0L) | |
49 return 1; | |
50 else if (arg == 0.0L) | |
51 { | |
52 /* Distinguish 0.0L and -0.0L. */ | |
53 static long double plus_zero = 0.0L; | |
54 long double arg_mem = arg; | |
55 return (memcmp (&plus_zero, &arg_mem, SIZEOF_LDBL) != 0); | |
56 } | |
57 else | |
58 return 0; | |
59 #endif | |
60 } |