summaryrefslogtreecommitdiffstats
path: root/lib/libm/src/s_logbl.c
diff options
context:
space:
mode:
authormartynas <martynas@openbsd.org>2008-12-09 20:00:35 +0000
committermartynas <martynas@openbsd.org>2008-12-09 20:00:35 +0000
commit390c8400525fc0ecc9e2c49c2246076b1b49fe19 (patch)
tree53eacecd5d140dfe4af32e85cbd374f340c935fc /lib/libm/src/s_logbl.c
parent- add long double signbit (diff)
downloadwireguard-openbsd-390c8400525fc0ecc9e2c49c2246076b1b49fe19.tar.xz
wireguard-openbsd-390c8400525fc0ecc9e2c49c2246076b1b49fe19.zip
- 80-bit and quad precision trigonometric and other most
important functions: acosl, asinl, atanl, atan2l, cosl, sinl, tanl, exp2l, frexpl, ilogbl, ldexpl, logbl, scalbnl, fabsl, hypotl, powl, sqrtl, rintl, copysignl, nanl, fdiml, fmaxl, fminl. mostly taken from freebsd, needed alot of changes to adapt. note, these are all c versions; and are quite slow when architectures have, e.g. sqrt. assembly versions will be added afterwards - make them .weak/__weak_alias to the double precision versions on other archs - no need to have two finites. finite() and finitef() are non-standard 3BSD obsolete versions of isfinite. remove from libm. make them weak_alias in libc to __isfinite and __isfinitef instead. similarly make 3BSD obsolete versions of isinf, isinff, isnan, isnanf weak_aliases to C99's __isinf, __isinff, __isnan, __isnanf - remove unused infinity.c. the c library has infinities for each supported platform - use STRICT_ASSIGN cast hack for _kernel_rem_pio2, so that the double version has a chance of working on i386 with extra precision - avoid storing multiple copies of the pi/2 array, since it won't vary - bump major due to removed finite/finitef. although they will be in libc, which anything is linked to, minor bump might be enough ok millert@. tested by sthen@, jsg@, ajacoutot@, kili@, naddy@
Diffstat (limited to 'lib/libm/src/s_logbl.c')
-rw-r--r--lib/libm/src/s_logbl.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/lib/libm/src/s_logbl.c b/lib/libm/src/s_logbl.c
new file mode 100644
index 00000000000..7de6ede4fd0
--- /dev/null
+++ b/lib/libm/src/s_logbl.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: s_logbl.c,v 1.1 2008/12/09 20:00:35 martynas Exp $ */
+/*
+ * From: @(#)s_ilogb.c 5.1 93/09/24
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/types.h>
+#include <machine/ieee.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+
+long double
+logbl(long double x)
+{
+ union {
+ long double e;
+ struct ieee_ext bits;
+ } u;
+ unsigned long m;
+ int b;
+
+ u.e = x;
+ if (u.bits.ext_exp == 0) {
+ if ((u.bits.ext_fracl
+#ifdef EXT_FRACLMBITS
+ | u.bits.ext_fraclm
+#endif /* EXT_FRACLMBITS */
+#ifdef EXT_FRACHMBITS
+ | u.bits.ext_frachm
+#endif /* EXT_FRACHMBITS */
+ | u.bits.ext_frach) == 0) { /* x == 0 */
+ u.bits.ext_sign = 1;
+ return (1.0L / u.e);
+ }
+ /* denormalized */
+ if (u.bits.ext_frach == 0
+#ifdef EXT_FRACHMBITS
+ && u.bits.ext_frachm == 0
+#endif
+ ) {
+ m = 1lu << (EXT_FRACLBITS - 1);
+ for (b = EXT_FRACHBITS; !(u.bits.ext_fracl & m); m >>= 1)
+ b++;
+#if defined(EXT_FRACHMBITS) && defined(EXT_FRACLMBITS)
+ m = 1lu << (EXT_FRACLMBITS - 1);
+ for (b += EXT_FRACHMBITS; !(u.bits.ext_fraclm & m);
+ m >>= 1)
+ b++;
+#endif /* defined(EXT_FRACHMBITS) && defined(EXT_FRACLMBITS) */
+ } else {
+ m = 1lu << (EXT_FRACHBITS - 1);
+ for (b = 0; !(u.bits.ext_frach & m); m >>= 1)
+ b++;
+#ifdef EXT_FRACHMBITS
+ m = 1lu << (EXT_FRACHMBITS - 1);
+ for (; !(u.bits.ext_frachm & m); m >>= 1)
+ b++;
+#endif /* EXT_FRACHMBITS */
+ }
+#ifdef EXT_IMPLICIT_NBIT
+ b++;
+#endif
+ return ((long double)(LDBL_MIN_EXP - b - 1));
+ }
+ if (u.bits.ext_exp < (LDBL_MAX_EXP << 1) - 1) /* normal */
+ return ((long double)(u.bits.ext_exp - LDBL_MAX_EXP + 1));
+ else /* +/- inf or nan */
+ return (x * x);
+}