diff options
author | Piotr Jasiukajtis <estibi@me.com> | 2014-02-04 20:31:57 +0100 |
---|---|---|
committer | Dan McDonald <danmcd@omniti.com> | 2014-10-17 18:00:52 -0400 |
commit | 25c28e83beb90e7c80452a7c818c5e6f73a07dc8 (patch) | |
tree | 95cb102e7fb37f52d4b3ec3e44508f352a335ee5 /usr/src/lib/libm/common/C/logb.c | |
parent | 4e6070e87069f63bef94d8e79c2fc3cab2c1ab6b (diff) | |
download | illumos-gate-25c28e83beb90e7c80452a7c818c5e6f73a07dc8.tar.gz |
693 Opensource replacement of sunwlibm
Reviewed by: Igor Kozhukhov ikozhukhov@gmail.com
Reviewed by: Keith M Wesolowski <keith.wesolowski@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/lib/libm/common/C/logb.c')
-rw-r--r-- | usr/src/lib/libm/common/C/logb.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/usr/src/lib/libm/common/C/logb.c b/usr/src/lib/libm/common/C/logb.c new file mode 100644 index 0000000000..71c31e069c --- /dev/null +++ b/usr/src/lib/libm/common/C/logb.c @@ -0,0 +1,85 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#if defined(ELFOBJ) +#pragma weak logb = __logb +#pragma weak _logb = __logb +#endif + +#include "libm.h" +#include "xpg6.h" /* __xpg6 */ +#define _C99SUSv3_logb _C99SUSv3_logb_subnormal_is_like_ilogb + +#if defined(USE_FPSCALE) || defined(__x86) +static const double two52 = 4503599627370496.0; +#else +/* + * v: high part of a non-zero subnormal |x|; w: low part of |x| + */ +static int +ilogb_subnormal(unsigned v, unsigned w) { + int r = -1022 - 52; + + if (v) + r += 32; + else + v = w; + if (v & 0xffff0000) + r += 16, v >>= 16; + if (v & 0xff00) + r += 8, v >>= 8; + if (v & 0xf0) + r += 4, v >>= 4; + v <<= 1; + return (r + ((0xffffaa50 >> v) & 0x3)); +} +#endif /* defined(USE_FPSCALE) */ + +double +logb(double x) { + int *px = (int *) &x, k = px[HIWORD] & ~0x80000000; + + if (k < 0x00100000) { + if ((px[LOWORD] | k) == 0) + return (_SVID_libm_err(x, x, 45)); + else if ((__xpg6 & _C99SUSv3_logb) != 0) { +#if defined(USE_FPSCALE) || defined(__x86) + x *= two52; + return ((double) (((px[HIWORD] & 0x7ff00000) >> 20) + - 1075)); +#else + return ((double) ilogb_subnormal(k, px[LOWORD])); +#endif + } else + return (-1022.0); + } else if (k < 0x7ff00000) + return ((double) ((k >> 20) - 1023)); + else + return (x * x); +} |