Mercurial > hg > octave-lojdl > gnulib-hg
annotate lib/trunc.c @ 9309:bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 07 Oct 2007 19:14:58 +0200 |
parents | 79e67a783774 |
children | 59fc463c9868 |
rev | line source |
---|---|
9282 | 1 /* Round towards zero. |
2 Copyright (C) 2007 Free Software Foundation, Inc. | |
3 | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
9285
diff
changeset
|
4 This program is free software: you can redistribute it and/or modify |
9282 | 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:
9285
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:
9285
diff
changeset
|
7 (at your option) any later version. |
9282 | 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:
9285
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:
9285
diff
changeset
|
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
9282 | 16 |
17 /* Written by Bruno Haible <bruno@clisp.org>, 2007. */ | |
18 | |
19 #include <config.h> | |
20 | |
21 /* Specification. */ | |
22 #include <math.h> | |
23 | |
24 #include <float.h> | |
25 | |
9285 | 26 #ifdef USE_LONG_DOUBLE |
27 # define FUNC truncl | |
28 # define DOUBLE long double | |
29 # define MANT_DIG LDBL_MANT_DIG | |
30 # define L_(literal) literal##L | |
31 #elif ! defined USE_FLOAT | |
32 # define FUNC trunc | |
33 # define DOUBLE double | |
34 # define MANT_DIG DBL_MANT_DIG | |
35 # define L_(literal) literal | |
36 #else /* defined USE_FLOAT */ | |
37 # define FUNC truncf | |
38 # define DOUBLE float | |
39 # define MANT_DIG FLT_MANT_DIG | |
40 # define L_(literal) literal##f | |
41 #endif | |
42 | |
43 /* 2^(MANT_DIG-1). */ | |
9282 | 44 static const double TWO_MANT_DIG = |
9285 | 45 /* Assume MANT_DIG <= 5 * 31. |
9282 | 46 Use the identity |
9285 | 47 n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */ |
48 (DOUBLE) (1U << ((MANT_DIG - 1) / 5)) | |
49 * (DOUBLE) (1U << ((MANT_DIG - 1 + 1) / 5)) | |
50 * (DOUBLE) (1U << ((MANT_DIG - 1 + 2) / 5)) | |
51 * (DOUBLE) (1U << ((MANT_DIG - 1 + 3) / 5)) | |
52 * (DOUBLE) (1U << ((MANT_DIG - 1 + 4) / 5)); | |
9282 | 53 |
9285 | 54 DOUBLE |
55 FUNC (DOUBLE x) | |
9282 | 56 { |
57 /* The use of 'volatile' guarantees that excess precision bits are dropped | |
58 at each addition step and before the following comparison at the caller's | |
59 site. It is necessary on x86 systems where double-floats are not IEEE | |
60 compliant by default, to avoid that the results become platform and compiler | |
61 option dependent. 'volatile' is a portable alternative to gcc's | |
62 -ffloat-store option. */ | |
9285 | 63 volatile DOUBLE y = x; |
64 volatile DOUBLE z = y; | |
9282 | 65 |
9285 | 66 if (z > L_(0.0)) |
9282 | 67 { |
68 /* Round to the next integer (nearest or up or down, doesn't matter). */ | |
69 z += TWO_MANT_DIG; | |
70 z -= TWO_MANT_DIG; | |
71 /* Enforce rounding down. */ | |
72 if (z > y) | |
9285 | 73 z -= L_(1.0); |
9282 | 74 } |
9285 | 75 else if (z < L_(0.0)) |
9282 | 76 { |
77 /* Round to the next integer (nearest or up or down, doesn't matter). */ | |
78 z -= TWO_MANT_DIG; | |
79 z += TWO_MANT_DIG; | |
80 /* Enforce rounding up. */ | |
81 if (z < y) | |
9285 | 82 z += L_(1.0); |
9282 | 83 } |
84 return z; | |
85 } |