1 | /*
|
---|
2 | * ====================================================
|
---|
3 | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
---|
4 | *
|
---|
5 | * Developed at SunPro, a Sun Microsystems, Inc. business.
|
---|
6 | * Permission to use, copy, modify, and distribute this
|
---|
7 | * software is freely granted, provided that this notice
|
---|
8 | * is preserved.
|
---|
9 | * ====================================================
|
---|
10 | *
|
---|
11 | * From: @(#)s_ceil.c 5.1 93/09/24
|
---|
12 | */
|
---|
13 |
|
---|
14 | #ifndef lint
|
---|
15 | static char rcsid[] = "$FreeBSD: src/lib/msun/src/s_ceill.c,v 1.3 2005/04/22 09:57:55 stefanf Exp $";
|
---|
16 | #endif
|
---|
17 |
|
---|
18 | /*
|
---|
19 | * ceill(x)
|
---|
20 | * Return x rounded toward -inf to integral value
|
---|
21 | * Method:
|
---|
22 | * Bit twiddling.
|
---|
23 | * Exception:
|
---|
24 | * Inexact flag raised if x not equal to ceill(x).
|
---|
25 | */
|
---|
26 |
|
---|
27 | #include <float.h>
|
---|
28 | #include <math.h>
|
---|
29 | #include <stdint.h>
|
---|
30 |
|
---|
31 | #include "fpmath.h"
|
---|
32 |
|
---|
33 | #ifdef LDBL_IMPLICIT_NBIT
|
---|
34 | #define MANH_SIZE (LDBL_MANH_SIZE + 1)
|
---|
35 | #define INC_MANH(u, c) do { \
|
---|
36 | uint64_t o = u.bits.manh; \
|
---|
37 | u.bits.manh += (c); \
|
---|
38 | if (u.bits.manh < o) \
|
---|
39 | u.bits.exp++; \
|
---|
40 | } while (0)
|
---|
41 | #else
|
---|
42 | #define MANH_SIZE LDBL_MANH_SIZE
|
---|
43 | #define INC_MANH(u, c) do { \
|
---|
44 | uint64_t o = u.bits.manh; \
|
---|
45 | u.bits.manh += (c); \
|
---|
46 | if (u.bits.manh < o) { \
|
---|
47 | u.bits.exp++; \
|
---|
48 | u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \
|
---|
49 | } \
|
---|
50 | } while (0)
|
---|
51 | #endif
|
---|
52 |
|
---|
53 | static const double huge = 1.0e300;
|
---|
54 |
|
---|
55 | long double
|
---|
56 | ceill(long double x)
|
---|
57 | {
|
---|
58 | union IEEEl2bits u = { .e = x };
|
---|
59 | int e = u.bits.exp - LDBL_MAX_EXP + 1;
|
---|
60 |
|
---|
61 | if (e < MANH_SIZE - 1) {
|
---|
62 | if (e < 0) { /* raise inexact if x != 0 */
|
---|
63 | if (huge + (double)x > 0.0)
|
---|
64 | if (u.bits.exp > 0 ||
|
---|
65 | (u.bits.manh | u.bits.manl) != 0)
|
---|
66 | u.e = u.bits.sign ? 0.0 : 1.0;
|
---|
67 | } else {
|
---|
68 | uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1);
|
---|
69 | if (((u.bits.manh & m) | u.bits.manl) == 0)
|
---|
70 | return (x); /* x is integral */
|
---|
71 | if (!u.bits.sign) {
|
---|
72 | #ifdef LDBL_IMPLICIT_NBIT
|
---|
73 | if (e == 0)
|
---|
74 | u.bits.exp++;
|
---|
75 | else
|
---|
76 | #endif
|
---|
77 | INC_MANH(u, 1llu << (MANH_SIZE - e - 1));
|
---|
78 | }
|
---|
79 | if (huge + (double)x > 0.0) { /* raise inexact flag */
|
---|
80 | u.bits.manh &= ~m;
|
---|
81 | u.bits.manl = 0;
|
---|
82 | }
|
---|
83 | }
|
---|
84 | } else if (e < LDBL_MANT_DIG - 1) {
|
---|
85 | uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1);
|
---|
86 | if ((u.bits.manl & m) == 0)
|
---|
87 | return (x); /* x is integral */
|
---|
88 | if (!u.bits.sign) {
|
---|
89 | if (e == MANH_SIZE - 1)
|
---|
90 | INC_MANH(u, 1);
|
---|
91 | else {
|
---|
92 | uint64_t o = u.bits.manl;
|
---|
93 | u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1);
|
---|
94 | if (u.bits.manl < o) /* got a carry */
|
---|
95 | INC_MANH(u, 1);
|
---|
96 | }
|
---|
97 | }
|
---|
98 | if (huge + (double)x > 0.0) /* raise inexact flag */
|
---|
99 | u.bits.manl &= ~m;
|
---|
100 | }
|
---|
101 | return (u.e);
|
---|
102 | }
|
---|