diff -Nur musl-0.9.13/.gitignore musl-git/.gitignore --- musl-0.9.13/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ musl-git/.gitignore 2013-09-16 20:31:39.000000000 +0200 @@ -0,0 +1,10 @@ +*.o +*.lo +*.a +*.so +*.so.1 +arch/*/bits/alltypes.h +config.mak +include/bits +tools/musl-gcc +lib/musl-gcc.specs diff -Nur musl-0.9.13/Makefile musl-git/Makefile --- musl-0.9.13/Makefile 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/Makefile 2013-09-16 20:31:39.000000000 +0200 @@ -157,7 +157,7 @@ $(INSTALL) -D -m 644 $< $@ $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so - $(INSTALL) -D -l $< $@ || true + $(INSTALL) -D -l $(libdir)/libc.so $@ || true install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),) diff -Nur musl-0.9.13/arch/microblaze/bits/limits.h musl-git/arch/microblaze/bits/limits.h --- musl-0.9.13/arch/microblaze/bits/limits.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/microblaze/bits/limits.h 2013-09-16 20:31:39.000000000 +0200 @@ -1,6 +1,5 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 #define LONG_BIT 32 #endif diff -Nur musl-0.9.13/arch/microblaze/reloc.h musl-git/arch/microblaze/reloc.h --- musl-0.9.13/arch/microblaze/reloc.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/microblaze/reloc.h 2013-09-16 20:31:39.000000000 +0200 @@ -49,7 +49,7 @@ for (a+=c+1; *a; a++); for (a++; *a; a+=2) if (*a<20) t[*a] = a[1]; base = (char *)t[AT_BASE]; - if (!base) base = (char *)(t[AT_PHDR] & -4096); + if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]); for (a=dynv; *a; a+=2) if (*a<20) t[*a] = a[1]; n = t[DT_RELASZ]; for (a=(void *)(base+t[DT_RELA]); n; a+=3, n-=12) diff -Nur musl-0.9.13/arch/mips/bits/limits.h musl-git/arch/mips/bits/limits.h --- musl-0.9.13/arch/mips/bits/limits.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/mips/bits/limits.h 2013-09-16 20:31:39.000000000 +0200 @@ -1,6 +1,5 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 #define LONG_BIT 32 #endif diff -Nur musl-0.9.13/arch/mips/bits/msg.h musl-git/arch/mips/bits/msg.h --- musl-0.9.13/arch/mips/bits/msg.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/mips/bits/msg.h 2013-09-16 20:31:39.000000000 +0200 @@ -1,12 +1,21 @@ struct msqid_ds { struct ipc_perm msg_perm; +#if _MIPSEL || __MIPSEL || __MIPSEL__ time_t msg_stime; int __unused1; time_t msg_rtime; int __unused2; time_t msg_ctime; int __unused3; +#else + int __unused1; + time_t msg_stime; + int __unused2; + time_t msg_rtime; + int __unused3; + time_t msg_ctime; +#endif unsigned long msg_cbytes; msgqnum_t msg_qnum; msglen_t msg_qbytes; diff -Nur musl-0.9.13/arch/mips/bits/shm.h musl-git/arch/mips/bits/shm.h --- musl-0.9.13/arch/mips/bits/shm.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/mips/bits/shm.h 2013-09-16 20:31:39.000000000 +0200 @@ -5,11 +5,8 @@ struct ipc_perm shm_perm; size_t shm_segsz; time_t shm_atime; - int __unused1; time_t shm_dtime; - int __unused2; time_t shm_ctime; - int __unused3; pid_t shm_cpid; pid_t shm_lpid; unsigned long shm_nattch; diff -Nur musl-0.9.13/arch/mips/reloc.h musl-git/arch/mips/reloc.h --- musl-0.9.13/arch/mips/reloc.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/mips/reloc.h 2013-09-16 20:31:39.000000000 +0200 @@ -51,7 +51,7 @@ for (a+=c+1; *a; a++); for (a++; *a; a+=2) if (*a<20) t[*a] = a[1]; base = (char *)t[AT_BASE]; - if (!base) base = (char *)(t[AT_PHDR] & -4096); + if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]); for (a=dynv; *a; a+=2) if (*a-0x70000000UL<20) t[*a&31] = a[1]; n = t[DT_MIPS_LOCAL_GOTNO - 0x70000000]; for (a=got; n; a++, n--) *a += (size_t)base; diff -Nur musl-0.9.13/arch/powerpc/bits/limits.h musl-git/arch/powerpc/bits/limits.h --- musl-0.9.13/arch/powerpc/bits/limits.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/powerpc/bits/limits.h 2013-09-16 20:31:39.000000000 +0200 @@ -1,6 +1,5 @@ #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) -#define PAGE_SIZE 4096 #define LONG_BIT 32 #endif diff -Nur musl-0.9.13/arch/powerpc/reloc.h musl-git/arch/powerpc/reloc.h --- musl-0.9.13/arch/powerpc/reloc.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/arch/powerpc/reloc.h 2013-09-16 20:31:39.000000000 +0200 @@ -46,7 +46,7 @@ for (a+=c+1; *a; a++); for (a++; *a; a+=2) if (*a<20) t[*a] = a[1]; base = (char *)t[AT_BASE]; - if (!base) base = (char *)(t[AT_PHDR] & -4096); + if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]); for (a=dynv; *a; a+=2) if (*a<20) t[*a] = a[1]; n = t[DT_RELASZ]; for (a=(void *)(base+t[DT_RELA]); n; a+=3, n-=12) diff -Nur musl-0.9.13/include/elf.h musl-git/include/elf.h --- musl-0.9.13/include/elf.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/elf.h 2013-09-16 20:31:39.000000000 +0200 @@ -105,6 +105,7 @@ #define ELFOSABI_HPUX 1 #define ELFOSABI_NETBSD 2 #define ELFOSABI_LINUX 3 +#define ELFOSABI_GNU 3 #define ELFOSABI_SOLARIS 6 #define ELFOSABI_AIX 7 #define ELFOSABI_IRIX 8 @@ -211,7 +212,11 @@ #define EM_OPENRISC 92 #define EM_ARC_A5 93 #define EM_XTENSA 94 -#define EM_NUM 95 +#define EM_AARCH64 183 +#define EM_TILEPRO 188 +#define EM_MICROBLAZE 189 +#define EM_TILEGX 191 +#define EM_NUM 192 #define EM_ALPHA 0x9026 #define EV_NONE 0 @@ -487,6 +492,8 @@ #define PT_HIPROC 0x7fffffff +#define PN_XNUM 0xffff + #define PF_X (1 << 0) #define PF_W (1 << 1) @@ -512,12 +519,31 @@ #define NT_LWPSTATUS 16 #define NT_LWPSINFO 17 #define NT_PRFPXREG 20 +#define NT_SIGINFO 0x53494749 +#define NT_FILE 0x46494c45 #define NT_PRXFPREG 0x46e62b7f #define NT_PPC_VMX 0x100 #define NT_PPC_SPE 0x101 #define NT_PPC_VSX 0x102 #define NT_386_TLS 0x200 #define NT_386_IOPERM 0x201 +#define NT_X86_XSTATE 0x202 +#define NT_S390_HIGH_GPRS 0x300 +#define NT_S390_TIMER 0x301 +#define NT_S390_TODCMP 0x302 +#define NT_S390_TODPREG 0x303 +#define NT_S390_CTRS 0x304 +#define NT_S390_PREFIX 0x305 +#define NT_S390_LAST_BREAK 0x306 +#define NT_S390_SYSTEM_CALL 0x307 +#define NT_S390_TDB 0x308 +#define NT_ARM_VFP 0x400 +#define NT_ARM_TLS 0x401 +#define NT_ARM_HW_BREAK 0x402 +#define NT_ARM_HW_WATCH 0x403 +#define NT_METAG_CBUF 0x500 +#define NT_METAG_RPIPE 0x501 +#define NT_METAG_TLS 0x502 #define NT_VERSION 1 @@ -666,7 +692,15 @@ #define DF_1_ENDFILTEE 0x00004000 #define DF_1_DISPRELDNE 0x00008000 #define DF_1_DISPRELPND 0x00010000 - +#define DF_1_NODIRECT 0x00020000 +#define DF_1_IGNMULDEF 0x00040000 +#define DF_1_NOKSYMS 0x00080000 +#define DF_1_NOHDR 0x00100000 +#define DF_1_EDITED 0x00200000 +#define DF_1_NORELOC 0x00400000 +#define DF_1_SYMINTPOSE 0x00800000 +#define DF_1_GLOBAUDIT 0x01000000 +#define DF_1_SINGLETON 0x02000000 #define DTF_1_PARINIT 0x00000001 #define DTF_1_CONFEXP 0x00000002 @@ -832,6 +866,8 @@ #define AT_RANDOM 25 +#define AT_HWCAP2 26 + #define AT_EXECFN 31 @@ -979,6 +1015,7 @@ #define R_386_TLS_DTPMOD32 35 #define R_386_TLS_DTPOFF32 36 #define R_386_TLS_TPOFF32 37 +#define R_386_SIZE32 38 #define R_386_TLS_GOTDESC 39 #define R_386_TLS_DESC_CALL 40 #define R_386_TLS_DESC 41 @@ -1109,20 +1146,6 @@ #define DT_SPARC_NUM 2 - -#define HWCAP_SPARC_FLUSH 1 -#define HWCAP_SPARC_STBAR 2 -#define HWCAP_SPARC_SWAP 4 -#define HWCAP_SPARC_MULDIV 8 -#define HWCAP_SPARC_V9 16 -#define HWCAP_SPARC_ULTRA3 32 -#define HWCAP_SPARC_BLKINIT 64 -#define HWCAP_SPARC_N2 128 - - - - - #define EF_MIPS_NOREORDER 1 #define EF_MIPS_PIC 2 #define EF_MIPS_CPIC 4 @@ -1139,9 +1162,10 @@ #define EF_MIPS_ARCH_3 0x20000000 #define EF_MIPS_ARCH_4 0x30000000 #define EF_MIPS_ARCH_5 0x40000000 -#define EF_MIPS_ARCH_32 0x60000000 -#define EF_MIPS_ARCH_64 0x70000000 - +#define EF_MIPS_ARCH_32 0x50000000 +#define EF_MIPS_ARCH_64 0x60000000 +#define EF_MIPS_ARCH_32R2 0x70000000 +#define EF_MIPS_ARCH_64R2 0x80000000 #define E_MIPS_ARCH_1 0x00000000 @@ -1149,8 +1173,8 @@ #define E_MIPS_ARCH_3 0x20000000 #define E_MIPS_ARCH_4 0x30000000 #define E_MIPS_ARCH_5 0x40000000 -#define E_MIPS_ARCH_32 0x60000000 -#define E_MIPS_ARCH_64 0x70000000 +#define E_MIPS_ARCH_32 0x50000000 +#define E_MIPS_ARCH_64 0x60000000 @@ -2020,7 +2044,8 @@ #define EF_ARM_VFP_FLOAT 0x400 #define EF_ARM_MAVERICK_FLOAT 0x800 - +#define EF_ARM_ABI_FLOAT_SOFT 0x200 +#define EF_ARM_ABI_FLOAT_HARD 0x400 #define EF_ARM_SYMSARESORTED 0x04 @@ -2064,6 +2089,17 @@ #define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) +#define R_AARCH64_NONE 0 +#define R_AARCH64_ABS64 257 +#define R_AARCH64_ABS32 258 +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 +#define R_AARCH64_JUMP_SLOT 1026 +#define R_AARCH64_RELATIVE 1027 +#define R_AARCH64_TLS_DTPMOD64 1028 +#define R_AARCH64_TLS_DTPREL64 1029 +#define R_AARCH64_TLS_TPREL64 1030 +#define R_AARCH64_TLSDESC 1031 #define R_ARM_NONE 0 @@ -2079,7 +2115,7 @@ #define R_ARM_THM_PC22 10 #define R_ARM_THM_PC8 11 #define R_ARM_AMP_VCALL9 12 -#define R_ARM_SWI24 13 +#define R_ARM_TLS_DESC 13 #define R_ARM_THM_SWI8 14 #define R_ARM_XPC25 15 #define R_ARM_THM_XPC22 16 @@ -2094,12 +2130,78 @@ #define R_ARM_GOTPC 25 #define R_ARM_GOT32 26 #define R_ARM_PLT32 27 +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_THM_JUMP24 30 +#define R_ARM_BASE_ABS 31 #define R_ARM_ALU_PCREL_7_0 32 #define R_ARM_ALU_PCREL_15_8 33 #define R_ARM_ALU_PCREL_23_15 34 #define R_ARM_LDR_SBREL_11_0 35 #define R_ARM_ALU_SBREL_19_12 36 #define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_TARGET1 38 +#define R_ARM_SBREL31 39 +#define R_ARM_V4BX 40 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 +#define R_ARM_MOVW_ABS_NC 43 +#define R_ARM_MOVT_ABS 44 +#define R_ARM_MOVW_PREL_NC 45 +#define R_ARM_MOVT_PREL 46 +#define R_ARM_THM_MOVW_ABS_NC 47 +#define R_ARM_THM_MOVT_ABS 48 +#define R_ARM_THM_MOVW_PREL_NC 49 +#define R_ARM_THM_MOVT_PREL 50 +#define R_ARM_THM_JUMP19 51 +#define R_ARM_THM_JUMP6 52 +#define R_ARM_THM_ALU_PREL_11_0 53 +#define R_ARM_THM_PC12 54 +#define R_ARM_ABS32_NOI 55 +#define R_ARM_REL32_NOI 56 +#define R_ARM_ALU_PC_G0_NC 57 +#define R_ARM_ALU_PC_G0 58 +#define R_ARM_ALU_PC_G1_NC 59 +#define R_ARM_ALU_PC_G1 60 +#define R_ARM_ALU_PC_G2 61 +#define R_ARM_LDR_PC_G1 62 +#define R_ARM_LDR_PC_G2 63 +#define R_ARM_LDRS_PC_G0 64 +#define R_ARM_LDRS_PC_G1 65 +#define R_ARM_LDRS_PC_G2 66 +#define R_ARM_LDC_PC_G0 67 +#define R_ARM_LDC_PC_G1 68 +#define R_ARM_LDC_PC_G2 69 +#define R_ARM_ALU_SB_G0_NC 70 +#define R_ARM_ALU_SB_G0 71 +#define R_ARM_ALU_SB_G1_NC 72 +#define R_ARM_ALU_SB_G1 73 +#define R_ARM_ALU_SB_G2 74 +#define R_ARM_LDR_SB_G0 75 +#define R_ARM_LDR_SB_G1 76 +#define R_ARM_LDR_SB_G2 77 +#define R_ARM_LDRS_SB_G0 78 +#define R_ARM_LDRS_SB_G1 79 +#define R_ARM_LDRS_SB_G2 80 +#define R_ARM_LDC_SB_G0 81 +#define R_ARM_LDC_SB_G1 82 +#define R_ARM_LDC_SB_G2 83 +#define R_ARM_MOVW_BREL_NC 84 +#define R_ARM_MOVT_BREL 85 +#define R_ARM_MOVW_BREL 86 +#define R_ARM_THM_MOVW_BREL_NC 87 +#define R_ARM_THM_MOVT_BREL 88 +#define R_ARM_THM_MOVW_BREL 89 +#define R_ARM_TLS_GOTDESC 90 +#define R_ARM_TLS_CALL 91 +#define R_ARM_TLS_DESCSEQ 92 +#define R_ARM_THM_TLS_CALL 93 +#define R_ARM_PLT32_ABS 94 +#define R_ARM_GOT_ABS 95 +#define R_ARM_GOT_PREL 96 +#define R_ARM_GOT_BREL12 97 +#define R_ARM_GOTOFF12 98 +#define R_ARM_GOTRELAX 99 #define R_ARM_GNU_VTENTRY 100 #define R_ARM_GNU_VTINHERIT 101 #define R_ARM_THM_PC11 102 @@ -2113,7 +2215,15 @@ #define R_ARM_TLS_IE32 107 #define R_ARM_TLS_LE32 108 - +#define R_ARM_TLS_LDO12 109 +#define R_ARM_TLS_LE12 110 +#define R_ARM_TLS_IE12GP 111 +#define R_ARM_ME_TOO 128 +#define R_ARM_THM_TLS_DESCSEQ 129 +#define R_ARM_THM_TLS_DESCSEQ16 129 +#define R_ARM_THM_TLS_DESCSEQ32 130 +#define R_ARM_THM_GOT_BREL12 131 +#define R_ARM_IRELATIVE 160 #define R_ARM_RXPC25 249 #define R_ARM_RSBREL32 250 #define R_ARM_THM_RPC22 251 @@ -2421,15 +2531,21 @@ #define R_X86_64_PC64 24 #define R_X86_64_GOTOFF64 25 #define R_X86_64_GOTPC32 26 - +#define R_X86_64_GOT64 27 +#define R_X86_64_GOTPCREL64 28 +#define R_X86_64_GOTPC64 29 +#define R_X86_64_GOTPLT64 30 +#define R_X86_64_PLTOFF64 31 +#define R_X86_64_SIZE32 32 +#define R_X86_64_SIZE64 33 #define R_X86_64_GOTPC32_TLSDESC 34 #define R_X86_64_TLSDESC_CALL 35 #define R_X86_64_TLSDESC 36 #define R_X86_64_IRELATIVE 37 - -#define R_X86_64_NUM 38 +#define R_X86_64_RELATIVE64 38 +#define R_X86_64_NUM 39 diff -Nur musl-0.9.13/include/limits.h musl-git/include/limits.h --- musl-0.9.13/include/limits.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/limits.h 2013-09-16 20:31:39.000000000 +0200 @@ -40,7 +40,9 @@ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) #define PIPE_BUF 4096 +#ifdef PAGE_SIZE #define PAGESIZE PAGE_SIZE +#endif #define FILESIZEBITS 64 #define NAME_MAX 255 #define SYMLINK_MAX 255 diff -Nur musl-0.9.13/include/net/if_arp.h musl-git/include/net/if_arp.h --- musl-0.9.13/include/net/if_arp.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/net/if_arp.h 2013-09-16 20:31:39.000000000 +0200 @@ -52,6 +52,7 @@ #define ARPHRD_ROSE 270 #define ARPHRD_X25 271 #define ARPHRD_HWX25 272 +#define ARPHRD_CAN 280 #define ARPHRD_PPP 512 #define ARPHRD_CISCO 513 #define ARPHRD_HDLC ARPHRD_CISCO @@ -84,7 +85,12 @@ #define ARPHRD_IEEE80211_PRISM 802 #define ARPHRD_IEEE80211_RADIOTAP 803 #define ARPHRD_IEEE802154 804 -#define ARPHRD_IEEE802154_PHY 805 +#define ARPHRD_IEEE802154_MONITOR 805 +#define ARPHRD_PHONET 820 +#define ARPHRD_PHONET_PIPE 821 +#define ARPHRD_CAIF 822 +#define ARPHRD_IP6GRE 823 +#define ARPHRD_NETLINK 824 #define ARPHRD_VOID 0xFFFF #define ARPHRD_NONE 0xFFFE diff -Nur musl-0.9.13/include/netinet/in.h musl-git/include/netinet/in.h --- musl-0.9.13/include/netinet/in.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/netinet/in.h 2013-09-16 20:31:39.000000000 +0200 @@ -91,10 +91,12 @@ #define IPPROTO_NONE 59 #define IPPROTO_DSTOPTS 60 #define IPPROTO_MTP 92 +#define IPPROTO_BEETPH 94 #define IPPROTO_ENCAP 98 #define IPPROTO_PIM 103 #define IPPROTO_COMP 108 #define IPPROTO_SCTP 132 +#define IPPROTO_MH 135 #define IPPROTO_UDPLITE 136 #define IPPROTO_RAW 255 #define IPPROTO_MAX 256 diff -Nur musl-0.9.13/include/sys/ptrace.h musl-git/include/sys/ptrace.h --- musl-0.9.13/include/sys/ptrace.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/sys/ptrace.h 2013-09-16 20:31:39.000000000 +0200 @@ -37,6 +37,8 @@ #define PTRACE_INTERRUPT 0x4207 #define PTRACE_LISTEN 0x4208 #define PTRACE_PEEKSIGINFO 0x4209 +#define PTRACE_GETSIGMASK 0x420a +#define PTRACE_SETSIGMASK 0x420b #define PT_READ_I PTRACE_PEEKTEXT #define PT_READ_D PTRACE_PEEKDATA diff -Nur musl-0.9.13/include/sys/resource.h musl-git/include/sys/resource.h --- musl-0.9.13/include/sys/resource.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/sys/resource.h 2013-09-16 20:31:39.000000000 +0200 @@ -59,6 +59,9 @@ #define prlimit64 prlimit #endif +#define PRIO_MIN (-20) +#define PRIO_MAX 20 + #define PRIO_PROCESS 0 #define PRIO_PGRP 1 #define PRIO_USER 2 diff -Nur musl-0.9.13/include/sys/socket.h musl-git/include/sys/socket.h --- musl-0.9.13/include/sys/socket.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/include/sys/socket.h 2013-09-16 20:31:39.000000000 +0200 @@ -199,6 +199,7 @@ #define SO_NOFCS 43 #define SO_LOCK_FILTER 44 #define SO_SELECT_ERR_QUEUE 45 +#define SO_BUSY_POLL 46 #ifndef SOL_SOCKET #define SOL_SOCKET 1 diff -Nur musl-0.9.13/include/wait.h musl-git/include/wait.h --- musl-0.9.13/include/wait.h 1970-01-01 01:00:00.000000000 +0100 +++ musl-git/include/wait.h 2013-09-16 20:31:39.000000000 +0200 @@ -0,0 +1,2 @@ +#warning redirecting incorrect #include to +#include diff -Nur musl-0.9.13/src/aio/aio_readwrite.c musl-git/src/aio/aio_readwrite.c --- musl-0.9.13/src/aio/aio_readwrite.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/aio/aio_readwrite.c 2013-09-16 20:31:39.000000000 +0200 @@ -2,8 +2,8 @@ #include #include #include -#include #include "pthread_impl.h" +#include "libc.h" static void dummy(void) { diff -Nur musl-0.9.13/src/aio/lio_listio.c musl-git/src/aio/lio_listio.c --- musl-0.9.13/src/aio/lio_listio.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/aio/lio_listio.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,9 +1,9 @@ #include #include -#include #include #include #include "pthread_impl.h" +#include "libc.h" struct lio_state { struct sigevent *sev; diff -Nur musl-0.9.13/src/conf/fpathconf.c musl-git/src/conf/fpathconf.c --- musl-0.9.13/src/conf/fpathconf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/conf/fpathconf.c 2013-09-16 20:31:39.000000000 +0200 @@ -19,11 +19,11 @@ [_PC_PRIO_IO] = -1, [_PC_SOCK_MAXBUF] = -1, [_PC_FILESIZEBITS] = FILESIZEBITS, - [_PC_REC_INCR_XFER_SIZE] = PAGE_SIZE, - [_PC_REC_MAX_XFER_SIZE] = PAGE_SIZE, - [_PC_REC_MIN_XFER_SIZE] = PAGE_SIZE, - [_PC_REC_XFER_ALIGN] = PAGE_SIZE, - [_PC_ALLOC_SIZE_MIN] = PAGE_SIZE, + [_PC_REC_INCR_XFER_SIZE] = 4096, + [_PC_REC_MAX_XFER_SIZE] = 4096, + [_PC_REC_MIN_XFER_SIZE] = 4096, + [_PC_REC_XFER_ALIGN] = 4096, + [_PC_ALLOC_SIZE_MIN] = 4096, [_PC_SYMLINK_MAX] = SYMLINK_MAX, [_PC_2_SYMLINKS] = 1 }; diff -Nur musl-0.9.13/src/conf/sysconf.c musl-git/src/conf/sysconf.c --- musl-0.9.13/src/conf/sysconf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/conf/sysconf.c 2013-09-16 20:31:39.000000000 +0200 @@ -3,6 +3,7 @@ #include #include #include "syscall.h" +#include "libc.h" #define VER (-2) #define OFLOW (-3) @@ -40,9 +41,9 @@ [_SC_AIO_PRIO_DELTA_MAX] = 0, /* ?? */ [_SC_DELAYTIMER_MAX] = _POSIX_DELAYTIMER_MAX, [_SC_MQ_OPEN_MAX] = -1, - [_SC_MQ_PRIO_MAX] = MQ_PRIO_MAX, + [_SC_MQ_PRIO_MAX] = OFLOW, [_SC_VERSION] = VER, - [_SC_PAGE_SIZE] = PAGE_SIZE, + [_SC_PAGE_SIZE] = OFLOW, [_SC_RTSIG_MAX] = 63, /* ?? */ [_SC_SEM_NSEMS_MAX] = SEM_NSEMS_MAX, [_SC_SEM_VALUE_MAX] = OFLOW, @@ -221,6 +222,9 @@ } else if (values[name] == OFLOW) { if (name == _SC_ARG_MAX) return ARG_MAX; if (name == _SC_SEM_VALUE_MAX) return SEM_VALUE_MAX; + if (name == _SC_MQ_PRIO_MAX) return MQ_PRIO_MAX; + /* name == _SC_PAGE_SIZE */ + return PAGE_SIZE; } else if (values[name] == CPUCNT) { unsigned char set[128] = {1}; int i, cnt; diff -Nur musl-0.9.13/src/env/__libc_start_main.c musl-git/src/env/__libc_start_main.c --- musl-0.9.13/src/env/__libc_start_main.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/env/__libc_start_main.c 2013-09-16 20:31:39.000000000 +0200 @@ -26,6 +26,7 @@ for (i=0; auxv[i]; i+=2) if (auxv[i] #include +#include struct __libc { void *main_thread; @@ -14,10 +15,15 @@ FILE *ofl_head; int ofl_lock[2]; size_t tls_size; + size_t page_size; }; extern size_t __hwcap; +#ifndef PAGE_SIZE +#define PAGE_SIZE libc.page_size +#endif + #if !defined(__PIC__) || (100*__GNUC__+__GNUC_MINOR__ >= 303 && !defined(__PCC__)) #ifdef __PIC__ diff -Nur musl-0.9.13/src/internal/libm.h musl-git/src/internal/libm.h --- musl-0.9.13/src/internal/libm.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/internal/libm.h 2013-09-16 20:31:39.000000000 +0200 @@ -17,117 +17,115 @@ #include #include #include +#include -#include "longdbl.h" - -#include "libc.h" - -union fshape { - float value; - uint32_t bits; +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + uint16_t se; + } i; }; - -union dshape { - double value; - uint64_t bits; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; }; +#else +#error Unsupported long double representation +#endif -#define FORCE_EVAL(x) do { \ - if (sizeof(x) == sizeof(float)) { \ - volatile float __x; \ - __x = (x); \ - } else if (sizeof(x) == sizeof(double)) { \ - volatile double __x; \ - __x = (x); \ - } else { \ - volatile long double __x; \ - __x = (x); \ - } \ +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + volatile float __x; \ + __x = (x); \ + } else if (sizeof(x) == sizeof(double)) { \ + volatile double __x; \ + __x = (x); \ + } else { \ + volatile long double __x; \ + __x = (x); \ + } \ } while(0) /* Get two 32 bit ints from a double. */ -#define EXTRACT_WORDS(hi,lo,d) \ -do { \ - union dshape __u; \ - __u.value = (d); \ - (hi) = __u.bits >> 32; \ - (lo) = (uint32_t)__u.bits; \ -} while (0) - -/* Get a 64 bit int from a double. */ -#define EXTRACT_WORD64(i,d) \ -do { \ - union dshape __u; \ - __u.value = (d); \ - (i) = __u.bits; \ +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + (hi) = __u.i >> 32; \ + (lo) = (uint32_t)__u.i; \ } while (0) /* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD(i,d) \ -do { \ - union dshape __u; \ - __u.value = (d); \ - (i) = __u.bits >> 32; \ +#define GET_HIGH_WORD(hi,d) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + (hi) = __u.i >> 32; \ } while (0) /* Get the less significant 32 bit int from a double. */ -#define GET_LOW_WORD(i,d) \ -do { \ - union dshape __u; \ - __u.value = (d); \ - (i) = (uint32_t)__u.bits; \ +#define GET_LOW_WORD(lo,d) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + (lo) = (uint32_t)__u.i; \ } while (0) /* Set a double from two 32 bit ints. */ -#define INSERT_WORDS(d,hi,lo) \ -do { \ - union dshape __u; \ - __u.bits = ((uint64_t)(hi) << 32) | (uint32_t)(lo); \ - (d) = __u.value; \ -} while (0) - -/* Set a double from a 64 bit int. */ -#define INSERT_WORD64(d,i) \ -do { \ - union dshape __u; \ - __u.bits = (i); \ - (d) = __u.value; \ +#define INSERT_WORDS(d,hi,lo) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \ + (d) = __u.f; \ } while (0) /* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD(d,hi) \ -do { \ - union dshape __u; \ - __u.value = (d); \ - __u.bits &= 0xffffffff; \ - __u.bits |= (uint64_t)(hi) << 32; \ - (d) = __u.value; \ +#define SET_HIGH_WORD(d,hi) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + __u.i &= 0xffffffff; \ + __u.i |= (uint64_t)(hi) << 32; \ + (d) = __u.f; \ } while (0) /* Set the less significant 32 bits of a double from an int. */ -#define SET_LOW_WORD(d,lo) \ -do { \ - union dshape __u; \ - __u.value = (d); \ - __u.bits &= 0xffffffff00000000ull; \ - __u.bits |= (uint32_t)(lo); \ - (d) = __u.value; \ +#define SET_LOW_WORD(d,lo) \ +do { \ + union {double f; uint64_t i;} __u; \ + __u.f = (d); \ + __u.i &= 0xffffffff00000000ull; \ + __u.i |= (uint32_t)(lo); \ + (d) = __u.f; \ } while (0) /* Get a 32 bit int from a float. */ -#define GET_FLOAT_WORD(i,d) \ -do { \ - union fshape __u; \ - __u.value = (d); \ - (i) = __u.bits; \ +#define GET_FLOAT_WORD(w,d) \ +do { \ + union {float f; uint32_t i;} __u; \ + __u.f = (d); \ + (w) = __u.i; \ } while (0) /* Set a float from a 32 bit int. */ -#define SET_FLOAT_WORD(d,i) \ -do { \ - union fshape __u; \ - __u.bits = (i); \ - (d) = __u.value; \ +#define SET_FLOAT_WORD(d,w) \ +do { \ + union {float f; uint32_t i;} __u; \ + __u.i = (w); \ + (d) = __u.f; \ } while (0) /* fdlibm kernel functions */ @@ -157,15 +155,4 @@ long double __polevll(long double, const long double *, int); long double __p1evll(long double, const long double *, int); -#if 0 -/* Attempt to get strict C99 semantics for assignment with non-C99 compilers. */ -#define STRICT_ASSIGN(type, lval, rval) do { \ - volatile type __v = (rval); \ - (lval) = __v; \ -} while (0) -#else -/* Should work with -fexcess-precision=standard (>=gcc-4.5) or -ffloat-store */ -#define STRICT_ASSIGN(type, lval, rval) ((lval) = (type)(rval)) -#endif - #endif diff -Nur musl-0.9.13/src/internal/longdbl.h musl-git/src/internal/longdbl.h --- musl-0.9.13/src/internal/longdbl.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/internal/longdbl.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,137 +0,0 @@ -#ifndef _LDHACK_H -#define _LDHACK_H - -#include -#include - -#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 -#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 -union ldshape { - long double value; - struct { - uint64_t m; - uint16_t exp:15; - uint16_t sign:1; - uint16_t pad; - } bits; -}; -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 -union ldshape { - long double value; - struct { - uint64_t mlo; - uint64_t mhi:48; - uint16_t exp:15; - uint16_t sign:1; - } bits; -}; -#else -#error Unsupported long double representation -#endif - - -// FIXME: hacks to make freebsd+openbsd long double code happy - -// union and macros for freebsd - -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 - -union IEEEl2bits { - long double e; - struct { - uint32_t manl:32; - uint32_t manh:32; - uint32_t exp:15; - uint32_t sign:1; - uint32_t pad:16; - } bits; - struct { - uint64_t man:64; - uint32_t expsign:16; - uint32_t pad:16; - } xbits; -}; - -#define LDBL_MANL_SIZE 32 -#define LDBL_MANH_SIZE 32 -#define LDBL_NBIT (1ull << LDBL_MANH_SIZE-1) -#undef LDBL_IMPLICIT_NBIT -#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT) - -#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 -/* -// ld128 float.h -//#define LDBL_MAX 1.189731495357231765085759326628007016E+4932L -#define LDBL_MAX 0x1.ffffffffffffffffffffffffffffp+16383 -#define LDBL_MAX_EXP 16384 -#define LDBL_HAS_INFINITY 1 -//#define LDBL_MIN 3.362103143112093506262677817321752603E-4932L -#define LDBL_MIN 0x1p-16382 -#define LDBL_HAS_QUIET_NAN 1 -#define LDBL_HAS_DENORM 1 -//#define LDBL_EPSILON 1.925929944387235853055977942584927319E-34L -#define LDBL_EPSILON 0x1p-112 -#define LDBL_MANT_DIG 113 -#define LDBL_MIN_EXP (-16381) -#define LDBL_MAX_10_EXP 4932 -#define LDBL_DENORM_MIN 0x0.0000000000000000000000000001p-16381 -#define LDBL_MIN_10_EXP (-4931) -#define LDBL_DIG 33 -*/ - -union IEEEl2bits { - long double e; - struct { - uint64_t manl:64; - uint64_t manh:48; - uint32_t exp:15; - uint32_t sign:1; - } bits; - struct { - uint64_t unused0:64; - uint64_t unused1:48; - uint32_t expsign:16; - } xbits; -}; - -#define LDBL_MANL_SIZE 64 -#define LDBL_MANH_SIZE 48 -#define LDBL_NBIT (1ull << LDBL_MANH_SIZE) -#define LDBL_IMPLICIT_NBIT 1 -#define mask_nbit_l(u) - -#endif - - -// macros for openbsd - -#define GET_LDOUBLE_WORDS(se,mh,ml, f) do{ \ - union IEEEl2bits u; \ - u.e = (f); \ - (se) = u.xbits.expsign; \ - (mh) = u.bits.manh; \ - (ml) = u.bits.manl; \ -}while(0) - -#define SET_LDOUBLE_WORDS(f, se,mh,ml) do{ \ - union IEEEl2bits u; \ - u.xbits.expsign = (se); \ - u.bits.manh = (mh); \ - u.bits.manl = (ml); \ - (f) = u.e; \ -}while(0) - -#define GET_LDOUBLE_EXP(se, f) do{ \ - union IEEEl2bits u; \ - u.e = (f); \ - (se) = u.xbits.expsign; \ -}while(0) - -#define SET_LDOUBLE_EXP(f, se) do{ \ - union IEEEl2bits u; \ - u.e = (f); \ - u.xbits.expsign = (se); \ - (f) = u.e; \ -}while(0) - -#endif diff -Nur musl-0.9.13/src/ldso/dynlink.c musl-git/src/ldso/dynlink.c --- musl-0.9.13/src/ldso/dynlink.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/ldso/dynlink.c 2013-09-16 20:31:39.000000000 +0200 @@ -614,6 +614,8 @@ sys_path = ""; } fclose(f); + } else if (errno != ENOENT) { + sys_path = ""; } } if (!sys_path) sys_path = "/lib:/usr/local/lib:/usr/lib"; @@ -978,6 +980,7 @@ env_preload = 0; libc.secure = 1; } + libc.page_size = aux[AT_PAGESZ]; /* If the dynamic linker was invoked as a program itself, AT_BASE * will not be set. In that case, we assume the base address is diff -Nur musl-0.9.13/src/legacy/getpagesize.c musl-git/src/legacy/getpagesize.c --- musl-0.9.13/src/legacy/getpagesize.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/legacy/getpagesize.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,5 +1,5 @@ #include -#include +#include "libc.h" int getpagesize(void) { diff -Nur musl-0.9.13/src/legacy/valloc.c musl-git/src/legacy/valloc.c --- musl-0.9.13/src/legacy/valloc.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/legacy/valloc.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,6 +1,6 @@ #define _BSD_SOURCE #include -#include +#include "libc.h" void *valloc(size_t size) { diff -Nur musl-0.9.13/src/math/__cosl.c musl-git/src/math/__cosl.c --- musl-0.9.13/src/math/__cosl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__cosl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,4 +1,5 @@ /* origin: FreeBSD /usr/src/lib/msun/ld80/k_cosl.c */ +/* origin: FreeBSD /usr/src/lib/msun/ld128/k_cosl.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. @@ -14,7 +15,8 @@ #include "libm.h" -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 +#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +#if LDBL_MANT_DIG == 64 /* * ld80 version of __cos.c. See __cos.c for most comments. */ @@ -43,7 +45,6 @@ */ static const long double C1 = 0.0416666666666666666136L; /* 0xaaaaaaaaaaaaaa9b.0p-68 */ - static const double C2 = -0.0013888888888888874, /* -0x16c16c16c16c10.0p-62 */ C3 = 0.000024801587301571716, /* 0x1a01a01a018e22.0p-68 */ @@ -51,13 +52,43 @@ C5 = 0.0000000020876754400407278, /* 0x11eed8caaeccf1.0p-81 */ C6 = -1.1470297442401303e-11, /* -0x19393412bd1529.0p-89 */ C7 = 4.7383039476436467e-14; /* 0x1aac9d9af5c43e.0p-97 */ +#define POLY(z) (z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*C7))))))) +#elif LDBL_MANT_DIG == 113 +/* + * ld128 version of __cos.c. See __cos.c for most comments. + */ +/* + * Domain [-0.7854, 0.7854], range ~[-1.80e-37, 1.79e-37]: + * |cos(x) - c(x))| < 2**-122.0 + * + * 113-bit precision requires more care than 64-bit precision, since + * simple methods give a minimax polynomial with coefficient for x^2 + * that is 1 ulp below 0.5, but we want it to be precisely 0.5. See + * above for more details. + */ +static const long double +C1 = 0.04166666666666666666666666666666658424671L, +C2 = -0.001388888888888888888888888888863490893732L, +C3 = 0.00002480158730158730158730158600795304914210L, +C4 = -0.2755731922398589065255474947078934284324e-6L, +C5 = 0.2087675698786809897659225313136400793948e-8L, +C6 = -0.1147074559772972315817149986812031204775e-10L, +C7 = 0.4779477332386808976875457937252120293400e-13L; +static const double +C8 = -0.1561920696721507929516718307820958119868e-15, +C9 = 0.4110317413744594971475941557607804508039e-18, +C10 = -0.8896592467191938803288521958313920156409e-21, +C11 = 0.1601061435794535138244346256065192782581e-23; +#define POLY(z) (z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*(C7+ \ + z*(C8+z*(C9+z*(C10+z*C11))))))))))) +#endif long double __cosl(long double x, long double y) { long double hz,z,r,w; z = x*x; - r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*(C6+z*C7)))))); + r = POLY(z); hz = 0.5*z; w = 1.0-hz; return w + (((1.0-w)-hz) + (z*r-x*y)); diff -Nur musl-0.9.13/src/math/__fpclassify.c musl-git/src/math/__fpclassify.c --- musl-0.9.13/src/math/__fpclassify.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__fpclassify.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,11 @@ -#include "libm.h" +#include +#include int __fpclassify(double x) { - union dshape u = { x }; - int e = u.bits>>52 & 0x7ff; - if (!e) return u.bits<<1 ? FP_SUBNORMAL : FP_ZERO; - if (e==0x7ff) return u.bits<<12 ? FP_NAN : FP_INFINITE; + union {double f; uint64_t i;} u = {x}; + int e = u.i>>52 & 0x7ff; + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; + if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE; return FP_NORMAL; } diff -Nur musl-0.9.13/src/math/__fpclassifyf.c musl-git/src/math/__fpclassifyf.c --- musl-0.9.13/src/math/__fpclassifyf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__fpclassifyf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,11 @@ -#include "libm.h" +#include +#include int __fpclassifyf(float x) { - union fshape u = { x }; - int e = u.bits>>23 & 0xff; - if (!e) return u.bits<<1 ? FP_SUBNORMAL : FP_ZERO; - if (e==0xff) return u.bits<<9 ? FP_NAN : FP_INFINITE; + union {float f; uint32_t i;} u = {x}; + int e = u.i>>23 & 0xff; + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; + if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE; return FP_NORMAL; } diff -Nur musl-0.9.13/src/math/__fpclassifyl.c musl-git/src/math/__fpclassifyl.c --- musl-0.9.13/src/math/__fpclassifyl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__fpclassifyl.c 2013-09-16 20:31:39.000000000 +0200 @@ -5,26 +5,28 @@ #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 int __fpclassifyl(long double x) { - union ldshape u = { x }; - int e = u.bits.exp; - if (!e) { - if (u.bits.m >> 63) return FP_NAN; - else if (u.bits.m) return FP_SUBNORMAL; - else return FP_ZERO; - } + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + int msb = u.i.m>>63; + if (!e && !msb) + return u.i.m ? FP_SUBNORMAL : FP_ZERO; + if (!msb) + return FP_NAN; if (e == 0x7fff) - return u.bits.m & (uint64_t)-1>>1 ? FP_NAN : FP_INFINITE; - return u.bits.m & (uint64_t)1<<63 ? FP_NORMAL : FP_NAN; + return u.i.m << 1 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; } #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 int __fpclassifyl(long double x) { - union ldshape u = { x }; - int e = u.bits.exp; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; if (!e) - return u.bits.mlo | u.bits.mhi ? FP_SUBNORMAL : FP_ZERO; - if (e == 0x7fff) - return u.bits.mlo | u.bits.mhi ? FP_NAN : FP_INFINITE; + return u.i2.lo | u.i2.hi ? FP_SUBNORMAL : FP_ZERO; + if (e == 0x7fff) { + u.i.se = 0; + return u.i2.lo | u.i2.hi ? FP_NAN : FP_INFINITE; + } return FP_NORMAL; } #endif diff -Nur musl-0.9.13/src/math/__invtrigl.c musl-git/src/math/__invtrigl.c --- musl-0.9.13/src/math/__invtrigl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__invtrigl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,7 +1,7 @@ +#include #include "__invtrigl.h" #if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 - static const long double pS0 = 1.66666666666666666631e-01L, pS1 = -4.16313987993683104320e-01L, @@ -28,4 +28,36 @@ q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*(qS4+z*qS5)))); return p/q; } +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 +static const long double +pS0 = 1.66666666666666666666666666666700314e-01L, +pS1 = -7.32816946414566252574527475428622708e-01L, +pS2 = 1.34215708714992334609030036562143589e+00L, +pS3 = -1.32483151677116409805070261790752040e+00L, +pS4 = 7.61206183613632558824485341162121989e-01L, +pS5 = -2.56165783329023486777386833928147375e-01L, +pS6 = 4.80718586374448793411019434585413855e-02L, +pS7 = -4.42523267167024279410230886239774718e-03L, +pS8 = 1.44551535183911458253205638280410064e-04L, +pS9 = -2.10558957916600254061591040482706179e-07L, +qS1 = -4.84690167848739751544716485245697428e+00L, +qS2 = 9.96619113536172610135016921140206980e+00L, +qS3 = -1.13177895428973036660836798461641458e+01L, +qS4 = 7.74004374389488266169304117714658761e+00L, +qS5 = -3.25871986053534084709023539900339905e+00L, +qS6 = 8.27830318881232209752469022352928864e-01L, +qS7 = -1.18768052702942805423330715206348004e-01L, +qS8 = 8.32600764660522313269101537926539470e-03L, +qS9 = -1.99407384882605586705979504567947007e-04L; + +const long double pio2_hi = 1.57079632679489661923132169163975140L; +const long double pio2_lo = 4.33590506506189051239852201302167613e-35L; + +long double __invtrigl_R(long double z) +{ + long double p, q; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*(pS5+z*(pS6+z*(pS7+z*(pS8+z*pS9))))))))); + q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*(qS4+z*(qS5+z*(pS6+z*(pS7+z*(pS8+z*pS9)))))))); + return p/q; +} #endif diff -Nur musl-0.9.13/src/math/__invtrigl.h musl-git/src/math/__invtrigl.h --- musl-0.9.13/src/math/__invtrigl.h 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__invtrigl.h 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,6 @@ -#include - -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 /* shared by acosl, asinl and atan2l */ #define pio2_hi __pio2_hi #define pio2_lo __pio2_lo extern const long double pio2_hi, pio2_lo; long double __invtrigl_R(long double z); -#endif diff -Nur musl-0.9.13/src/math/__rem_pio2.c musl-git/src/math/__rem_pio2.c --- musl-0.9.13/src/math/__rem_pio2.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__rem_pio2.c 2013-09-16 20:31:39.000000000 +0200 @@ -112,7 +112,7 @@ uint32_t high; medium: /* Use a specialized rint() to get fn. Assume round-to-nearest. */ - STRICT_ASSIGN(double, fn, x*invpio2 + 0x1.8p52); + fn = x*invpio2 + 0x1.8p52; fn = fn - 0x1.8p52; // FIXME #ifdef HAVE_EFFICIENT_IRINT diff -Nur musl-0.9.13/src/math/__rem_pio2_large.c musl-git/src/math/__rem_pio2_large.c --- musl-0.9.13/src/math/__rem_pio2_large.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__rem_pio2_large.c 2013-09-16 20:31:39.000000000 +0200 @@ -415,7 +415,8 @@ fw = 0.0; for (i=jz; i>=0; i--) fw += fq[i]; - STRICT_ASSIGN(double,fw,fw); + // TODO: drop excess precision here once double_t is used + fw = (double)fw; y[0] = ih==0 ? fw : -fw; fw = fq[0]-fw; for (i=1; i<=jz; i++) diff -Nur musl-0.9.13/src/math/__rem_pio2f.c musl-git/src/math/__rem_pio2f.c --- musl-0.9.13/src/math/__rem_pio2f.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__rem_pio2f.c 2013-09-16 20:31:39.000000000 +0200 @@ -44,7 +44,7 @@ /* 25+53 bit pi is good enough for medium size */ if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */ /* Use a specialized rint() to get fn. Assume round-to-nearest. */ - STRICT_ASSIGN(double, fn, x*invpio2 + 0x1.8p52); + fn = x*invpio2 + 0x1.8p52; fn = fn - 0x1.8p52; // FIXME #ifdef HAVE_EFFICIENT_IRINT diff -Nur musl-0.9.13/src/math/__rem_pio2l.c musl-git/src/math/__rem_pio2l.c --- musl-0.9.13/src/math/__rem_pio2l.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__rem_pio2l.c 2013-09-16 20:31:39.000000000 +0200 @@ -13,15 +13,22 @@ * Optimized by Bruce D. Evans. */ #include "libm.h" -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 -/* ld80 version of __rem_pio2(x,y) +#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +/* ld80 and ld128 version of __rem_pio2(x,y) * * return the remainder of x rem pi/2 in y[0]+y[1] * use __rem_pio2_large() for large x */ -#define BIAS (LDBL_MAX_EXP - 1) - +#if LDBL_MANT_DIG == 64 +/* u ~< 0x1p25*pi/2 */ +#define SMALL(u) (((u.i.se & 0x7fffU)<<16 | u.i.m>>48) < ((0x3fff + 25)<<16 | 0x921f>>1 | 0x8000)) +#define TOINT 0x1.8p63 +#define QUOBITS(x) ((uint32_t)(int32_t)x & 0x7fffffff) +#define ROUND1 22 +#define ROUND2 61 +#define NX 3 +#define NY 2 /* * invpio2: 64 bits of 2/pi * pio2_1: first 39 bits of pi/2 @@ -32,60 +39,61 @@ * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) */ static const double -two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ pio2_1 = 1.57079632679597125389e+00, /* 0x3FF921FB, 0x54444000 */ pio2_2 = -1.07463465549783099519e-12, /* -0x12e7b967674000.0p-92 */ pio2_3 = 6.36831716351370313614e-25; /* 0x18a2e037074000.0p-133 */ - static const long double invpio2 = 6.36619772367581343076e-01L, /* 0xa2f9836e4e44152a.0p-64 */ pio2_1t = -1.07463465549719416346e-12L, /* -0x973dcb3b399d747f.0p-103 */ pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */ pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */ +#elif LDBL_MANT_DIG == 113 +/* u ~< 0x1p45*pi/2 */ +#define SMALL(u) (((u.i.se & 0x7fffU)<<16 | u.i.top) < ((0x3fff + 45)<<16 | 0x921f)) +#define TOINT 0x1.8p112 +#define QUOBITS(x) ((uint32_t)(int64_t)x & 0x7fffffff) +#define ROUND1 51 +#define ROUND2 119 +#define NX 5 +#define NY 3 +static const long double +invpio2 = 6.3661977236758134307553505349005747e-01L, /* 0x145f306dc9c882a53f84eafa3ea6a.0p-113 */ +pio2_1 = 1.5707963267948966192292994253909555e+00L, /* 0x1921fb54442d18469800000000000.0p-112 */ +pio2_1t = 2.0222662487959507323996846200947577e-21L, /* 0x13198a2e03707344a4093822299f3.0p-181 */ +pio2_2 = 2.0222662487959507323994779168837751e-21L, /* 0x13198a2e03707344a400000000000.0p-181 */ +pio2_2t = 2.0670321098263988236496903051604844e-43L, /* 0x127044533e63a0105df531d89cd91.0p-254 */ +pio2_3 = 2.0670321098263988236499468110329591e-43L, /* 0x127044533e63a0105e00000000000.0p-254 */ +pio2_3t = -2.5650587247459238361625433492959285e-65L; /* -0x159c4ec64ddaeb5f78671cbfb2210.0p-327 */ +#endif int __rem_pio2l(long double x, long double *y) { - union IEEEl2bits u,u1; + union ldshape u,uz; long double z,w,t,r,fn; - double tx[3],ty[2]; - int e0,ex,i,j,nx,n; - int16_t expsign; - - u.e = x; - expsign = u.xbits.expsign; - ex = expsign & 0x7fff; - if (ex < BIAS + 25 || (ex == BIAS + 25 && u.bits.manh < 0xc90fdaa2)) { - union IEEEl2bits u2; - int ex1; + double tx[NX],ty[NY]; + int ex,ey,n,i; - /* |x| ~< 2^25*(pi/2), medium size */ - /* Use a specialized rint() to get fn. Assume round-to-nearest. */ - fn = x*invpio2 + 0x1.8p63; - fn = fn - 0x1.8p63; -// FIXME -//#ifdef HAVE_EFFICIENT_IRINT -// n = irint(fn); -//#else - n = fn; -//#endif + u.f = x; + ex = u.i.se & 0x7fff; + if (SMALL(u)) { + /* rint(x/(pi/2)), Assume round-to-nearest. */ + fn = x*invpio2 + TOINT - TOINT; + n = QUOBITS(fn); r = x-fn*pio2_1; - w = fn*pio2_1t; /* 1st round good to 102 bit */ - j = ex; + w = fn*pio2_1t; /* 1st round good to 102/180 bits (ld80/ld128) */ y[0] = r-w; - u2.e = y[0]; - ex1 = u2.xbits.expsign & 0x7fff; - i = j-ex1; - if (i > 22) { /* 2nd iteration needed, good to 141 */ + u.f = y[0]; + ey = u.i.se & 0x7fff; + if (ex - ey > ROUND1) { /* 2nd iteration needed, good to 141/248 (ld80/ld128) */ t = r; w = fn*pio2_2; r = t-w; w = fn*pio2_2t-((t-r)-w); y[0] = r-w; - u2.e = y[0]; - ex1 = u2.xbits.expsign & 0x7fff; - i = j-ex1; - if (i > 61) { /* 3rd iteration need, 180 bits acc */ - t = r; /* will cover all possible cases */ + u.f = y[0]; + ey = u.i.se & 0x7fff; + if (ex - ey > ROUND2) { /* 3rd iteration, good to 180/316 bits */ + t = r; /* will cover all possible cases (not verified for ld128) */ w = fn*pio2_3; r = t-w; w = fn*pio2_3t-((t-r)-w); @@ -102,23 +110,26 @@ y[0] = y[1] = x - x; return 0; } - /* set z = scalbn(|x|,ilogb(x)-23) */ - u1.e = x; - e0 = ex - BIAS - 23; /* e0 = ilogb(|x|)-23; */ - u1.xbits.expsign = ex - e0; - z = u1.e; - for (i=0; i<2; i++) { + /* set z = scalbn(|x|,-ilogb(x)+23) */ + uz.f = x; + uz.i.se = 0x3fff + 23; + z = uz.f; + for (i=0; i < NX - 1; i++) { tx[i] = (double)(int32_t)z; - z = (z-tx[i])*two24; + z = (z-tx[i])*0x1p24; } - tx[2] = z; - nx = 3; - while (tx[nx-1] == 0.0) - nx--; /* skip zero term */ - n = __rem_pio2_large(tx,ty,e0,nx,2); - r = (long double)ty[0] + ty[1]; - w = ty[1] - (r - ty[0]); - if (expsign < 0) { + tx[i] = z; + while (tx[i] == 0) + i--; + n = __rem_pio2_large(tx, ty, ex-0x3fff-23, i+1, NY); + w = ty[1]; + if (NY == 3) + w += ty[2]; + r = ty[0] + w; + /* TODO: for ld128 this does not follow the recommendation of the + comments of __rem_pio2_large which seem wrong if |ty[0]| > |ty[1]+ty[2]| */ + w -= r - ty[0]; + if (u.i.se >> 15) { y[0] = -r; y[1] = -w; return -n; diff -Nur musl-0.9.13/src/math/__signbitl.c musl-git/src/math/__signbitl.c --- musl-0.9.13/src/math/__signbitl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__signbitl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,11 +1,9 @@ #include "libm.h" -// FIXME: should be a macro #if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 int __signbitl(long double x) { union ldshape u = {x}; - - return u.bits.sign; + return u.i.se >> 15; } #endif diff -Nur musl-0.9.13/src/math/__sinl.c musl-git/src/math/__sinl.c --- musl-0.9.13/src/math/__sinl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__sinl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,4 +1,5 @@ /* origin: FreeBSD /usr/src/lib/msun/ld80/k_sinl.c */ +/* origin: FreeBSD /usr/src/lib/msun/ld128/k_sinl.c */ /* * ==================================================== * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. @@ -13,7 +14,8 @@ #include "libm.h" -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 +#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +#if LDBL_MANT_DIG == 64 /* * ld80 version of __sin.c. See __sin.c for most comments. */ @@ -23,10 +25,8 @@ * * See __cosl.c for more details about the polynomial. */ - static const long double S1 = -0.166666666666666666671L; /* -0xaaaaaaaaaaaaaaab.0p-66 */ - static const double S2 = 0.0083333333333333332, /* 0x11111111111111.0p-59 */ S3 = -0.00019841269841269427, /* -0x1a01a01a019f81.0p-65 */ @@ -35,6 +35,34 @@ S6 = 1.6059006598854211e-10, /* 0x161242b90243b5.0p-85 */ S7 = -7.6429779983024564e-13, /* -0x1ae42ebd1b2e00.0p-93 */ S8 = 2.6174587166648325e-15; /* 0x179372ea0b3f64.0p-101 */ +#define POLY(z) (S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*S8)))))) +#elif LDBL_MANT_DIG == 113 +/* + * ld128 version of __sin.c. See __sin.c for most comments. + */ +/* + * Domain [-0.7854, 0.7854], range ~[-1.53e-37, 1.659e-37] + * |sin(x)/x - s(x)| < 2**-122.1 + * + * See __cosl.c for more details about the polynomial. + */ +static const long double +S1 = -0.16666666666666666666666666666666666606732416116558L, +S2 = 0.0083333333333333333333333333333331135404851288270047L, +S3 = -0.00019841269841269841269841269839935785325638310428717L, +S4 = 0.27557319223985890652557316053039946268333231205686e-5L, +S5 = -0.25052108385441718775048214826384312253862930064745e-7L, +S6 = 0.16059043836821614596571832194524392581082444805729e-9L, +S7 = -0.76471637318198151807063387954939213287488216303768e-12L, +S8 = 0.28114572543451292625024967174638477283187397621303e-14L; +static const double +S9 = -0.82206352458348947812512122163446202498005154296863e-17, +S10 = 0.19572940011906109418080609928334380560135358385256e-19, +S11 = -0.38680813379701966970673724299207480965452616911420e-22, +S12 = 0.64038150078671872796678569586315881020659912139412e-25; +#define POLY(z) (S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*(S8+ \ + z*(S9+z*(S10+z*(S11+z*S12)))))))))) +#endif long double __sinl(long double x, long double y, int iy) { @@ -42,7 +70,7 @@ z = x*x; v = z*x; - r = S2+z*(S3+z*(S4+z*(S5+z*(S6+z*(S7+z*S8))))); + r = POLY(z); if (iy == 0) return x+v*(S1+z*r); return x-((z*(0.5*y-v*r)-y)-v*S1); diff -Nur musl-0.9.13/src/math/__tanl.c musl-git/src/math/__tanl.c --- musl-0.9.13/src/math/__tanl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/__tanl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,4 +1,5 @@ /* origin: FreeBSD /usr/src/lib/msun/ld80/k_tanl.c */ +/* origin: FreeBSD /usr/src/lib/msun/ld128/k_tanl.c */ /* * ==================================================== * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. @@ -12,7 +13,8 @@ #include "libm.h" -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 +#if (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +#if LDBL_MANT_DIG == 64 /* * ld80 version of __tan.c. See __tan.c for most comments. */ @@ -22,14 +24,12 @@ * * See __cosl.c for more details about the polynomial. */ - static const long double T3 = 0.333333333333333333180L, /* 0xaaaaaaaaaaaaaaa5.0p-65 */ T5 = 0.133333333333333372290L, /* 0x88888888888893c3.0p-66 */ T7 = 0.0539682539682504975744L, /* 0xdd0dd0dd0dc13ba2.0p-68 */ pio4 = 0.785398163397448309628L, /* 0xc90fdaa22168c235.0p-64 */ pio4lo = -1.25413940316708300586e-20L; /* -0xece675d1fc8f8cbb.0p-130 */ - static const double T9 = 0.021869488536312216, /* 0x1664f4882cc1c2.0p-58 */ T11 = 0.0088632355256619590, /* 0x1226e355c17612.0p-59 */ @@ -44,6 +44,59 @@ T29 = 0.0000078293456938132840, /* 0x106b59141a6cb3.0p-69 */ T31 = -0.0000032609076735050182, /* -0x1b5abef3ba4b59.0p-71 */ T33 = 0.0000023261313142559411; /* 0x13835436c0c87f.0p-71 */ +#define RPOLY(w) (T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 + \ + w * (T25 + w * (T29 + w * T33))))))) +#define VPOLY(w) (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 + \ + w * (T27 + w * T31)))))) +#elif LDBL_MANT_DIG == 113 +/* + * ld128 version of __tan.c. See __tan.c for most comments. + */ +/* + * Domain [-0.67434, 0.67434], range ~[-3.37e-36, 1.982e-37] + * |tan(x)/x - t(x)| < 2**-117.8 (XXX should be ~1e-37) + * + * See __cosl.c for more details about the polynomial. + */ +static const long double +T3 = 0x1.5555555555555555555555555553p-2L, +T5 = 0x1.1111111111111111111111111eb5p-3L, +T7 = 0x1.ba1ba1ba1ba1ba1ba1ba1b694cd6p-5L, +T9 = 0x1.664f4882c10f9f32d6bbe09d8bcdp-6L, +T11 = 0x1.226e355e6c23c8f5b4f5762322eep-7L, +T13 = 0x1.d6d3d0e157ddfb5fed8e84e27b37p-9L, +T15 = 0x1.7da36452b75e2b5fce9ee7c2c92ep-10L, +T17 = 0x1.355824803674477dfcf726649efep-11L, +T19 = 0x1.f57d7734d1656e0aceb716f614c2p-13L, +T21 = 0x1.967e18afcb180ed942dfdc518d6cp-14L, +T23 = 0x1.497d8eea21e95bc7e2aa79b9f2cdp-15L, +T25 = 0x1.0b132d39f055c81be49eff7afd50p-16L, +T27 = 0x1.b0f72d33eff7bfa2fbc1059d90b6p-18L, +T29 = 0x1.5ef2daf21d1113df38d0fbc00267p-19L, +T31 = 0x1.1c77d6eac0234988cdaa04c96626p-20L, +T33 = 0x1.cd2a5a292b180e0bdd701057dfe3p-22L, +T35 = 0x1.75c7357d0298c01a31d0a6f7d518p-23L, +T37 = 0x1.2f3190f4718a9a520f98f50081fcp-24L, +pio4 = 0x1.921fb54442d18469898cc51701b8p-1L, +pio4lo = 0x1.cd129024e088a67cc74020bbea60p-116L; +static const double +T39 = 0.000000028443389121318352, /* 0x1e8a7592977938.0p-78 */ +T41 = 0.000000011981013102001973, /* 0x19baa1b1223219.0p-79 */ +T43 = 0.0000000038303578044958070, /* 0x107385dfb24529.0p-80 */ +T45 = 0.0000000034664378216909893, /* 0x1dc6c702a05262.0p-81 */ +T47 = -0.0000000015090641701997785, /* -0x19ecef3569ebb6.0p-82 */ +T49 = 0.0000000029449552300483952, /* 0x194c0668da786a.0p-81 */ +T51 = -0.0000000022006995706097711, /* -0x12e763b8845268.0p-81 */ +T53 = 0.0000000015468200913196612, /* 0x1a92fc98c29554.0p-82 */ +T55 = -0.00000000061311613386849674, /* -0x151106cbc779a9.0p-83 */ +T57 = 1.4912469681508012e-10; /* 0x147edbdba6f43a.0p-85 */ +#define RPOLY(w) (T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 + \ + w * (T25 + w * (T29 + w * (T33 + w * (T37 + w * (T41 + \ + w * (T45 + w * (T49 + w * (T53 + w * T57))))))))))))) +#define VPOLY(w) (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 + \ + w * (T27 + w * (T31 + w * (T35 + w * (T39 + w * (T43 + \ + w * (T47 + w * (T51 + w * T55)))))))))))) +#endif long double __tanl(long double x, long double y, int odd) { long double z, r, v, w, s, a, t; @@ -62,10 +115,8 @@ } z = x * x; w = z * z; - r = T5 + w * (T9 + w * (T13 + w * (T17 + w * (T21 + - w * (T25 + w * (T29 + w * T33)))))); - v = z * (T7 + w * (T11 + w * (T15 + w * (T19 + w * (T23 + - w * (T27 + w * T31)))))); + r = RPOLY(w); + v = z * VPOLY(w); s = z * x; r = y + z * (s * (r + v) + y) + T3 * s; w = x + r; @@ -76,7 +127,6 @@ } if (!odd) return w; - /* * if allow error up to 2 ulp, simply return * -1.0 / (x+r) here diff -Nur musl-0.9.13/src/math/acoshf.c musl-git/src/math/acoshf.c --- musl-0.9.13/src/math/acoshf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/acoshf.c 2013-09-16 20:31:39.000000000 +0200 @@ -3,14 +3,15 @@ /* acosh(x) = log(x + sqrt(x*x-1)) */ float acoshf(float x) { - union {float f; int32_t i;} u = {.f = x}; + union {float f; uint32_t i;} u = {x}; + uint32_t a = u.i & 0x7fffffff; - if (u.i < 0x3f800000+(1<<23)) - /* x < 2, invalid if x < 1 or nan */ + if (a < 0x3f800000+(1<<23)) + /* |x| < 2, invalid if x < 1 or nan */ /* up to 2ulp error in [1,1.125] */ return log1pf(x-1 + sqrtf((x-1)*(x-1)+2*(x-1))); - if (u.i < 0x3f800000+(12<<23)) - /* x < 0x1p12 */ + if (a < 0x3f800000+(12<<23)) + /* |x| < 0x1p12 */ return logf(2*x - 1/(x+sqrtf(x*x-1))); /* x >= 0x1p12 */ return logf(x) + 0.693147180559945309417232121458176568f; diff -Nur musl-0.9.13/src/math/acoshl.c musl-git/src/math/acoshl.c --- musl-0.9.13/src/math/acoshl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/acoshl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,16 +9,14 @@ /* acosh(x) = log(x + sqrt(x*x-1)) */ long double acoshl(long double x) { - union { - long double f; - struct{uint64_t m; int16_t se; uint16_t pad;} i; - } u = {.f = x}; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; - if (u.i.se < 0x3fff + 1) - /* x < 2, invalid if x < 1 or nan */ + if (e < 0x3fff + 1) + /* |x| < 2, invalid if x < 1 or nan */ return log1pl(x-1 + sqrtl((x-1)*(x-1)+2*(x-1))); - if (u.i.se < 0x3fff + 32) - /* x < 0x1p32 */ + if (e < 0x3fff + 32) + /* |x| < 0x1p32 */ return logl(2*x - 1/(x+sqrtl(x*x-1))); return logl(x) + 0.693147180559945309417232121458176568L; } diff -Nur musl-0.9.13/src/math/acosl.c musl-git/src/math/acosl.c --- musl-0.9.13/src/math/acosl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/acosl.c 2013-09-16 20:31:39.000000000 +0200 @@ -23,46 +23,45 @@ } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 #include "__invtrigl.h" +#if LDBL_MANT_DIG == 64 +#define CLEARBOTTOM(u) (u.i.m &= -1ULL << 32) +#elif LDBL_MANT_DIG == 113 +#define CLEARBOTTOM(u) (u.i.lo = 0) +#endif long double acosl(long double x) { - union IEEEl2bits u; - long double z, w, s, c, df; - int16_t expsign, expt; - u.e = x; - expsign = u.xbits.expsign; - expt = expsign & 0x7fff; + union ldshape u = {x}; + long double z, s, c, f; + uint16_t e = u.i.se & 0x7fff; + /* |x| >= 1 or nan */ - if (expt >= 0x3fff) { - if (expt == 0x3fff && - ((u.bits.manh & ~LDBL_NBIT) | u.bits.manl) == 0) { - if (expsign > 0) - return 0; /* acos(1) = 0 */ - return 2*pio2_hi + 0x1p-120f; /* acos(-1)= pi */ - } - return 0/(x-x); /* acos(|x|>1) is NaN */ + if (e >= 0x3fff) { + if (x == 1) + return 0; + if (x == -1) + return 2*pio2_hi + 0x1p-120f; + return 0/(x-x); } /* |x| < 0.5 */ - if (expt < 0x3fff - 1) { - if (expt < 0x3fff - 65) - return pio2_hi + 0x1p-120f; /* x < 0x1p-65: acosl(x)=pi/2 */ - return pio2_hi - (x - (pio2_lo - x * __invtrigl_R(x*x))); + if (e < 0x3fff - 1) { + if (e < 0x3fff - LDBL_MANT_DIG - 1) + return pio2_hi + 0x1p-120f; + return pio2_hi - (__invtrigl_R(x*x)*x - pio2_lo + x); } /* x < -0.5 */ - if (expsign < 0) { - z = (1.0 + x) * 0.5; + if (u.i.se >> 15) { + z = (1 + x)*0.5; s = sqrtl(z); - w = __invtrigl_R(z) * s - pio2_lo; - return 2*(pio2_hi - (s + w)); + return 2*(pio2_hi - (__invtrigl_R(z)*s - pio2_lo + s)); } /* x > 0.5 */ - z = (1.0 - x) * 0.5; + z = (1 - x)*0.5; s = sqrtl(z); - u.e = s; - u.bits.manl = 0; - df = u.e; - c = (z - df * df) / (s + df); - w = __invtrigl_R(z) * s + c; - return 2*(df + w); + u.f = s; + CLEARBOTTOM(u); + f = u.f; + c = (z - f*f)/(s + f); + return 2*(__invtrigl_R(z)*s + c + f); } #endif diff -Nur musl-0.9.13/src/math/asinhl.c musl-git/src/math/asinhl.c --- musl-0.9.13/src/math/asinhl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/asinhl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,10 +9,7 @@ /* asinh(x) = sign(x)*log(|x|+sqrt(x*x+1)) ~= x - x^3/6 + o(x^5) */ long double asinhl(long double x) { - union { - long double f; - struct{uint64_t m; uint16_t se; uint16_t pad;} i; - } u = {.f = x}; + union ldshape u = {x}; unsigned e = u.i.se & 0x7fff; unsigned s = u.i.se >> 15; diff -Nur musl-0.9.13/src/math/asinl.c musl-git/src/math/asinl.c --- musl-0.9.13/src/math/asinl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/asinl.c 2013-09-16 20:31:39.000000000 +0200 @@ -23,27 +23,29 @@ } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 #include "__invtrigl.h" -/* 0.95 */ -#define THRESH ((0xe666666666666666ULL>>(64-(LDBL_MANH_SIZE-1)))|LDBL_NBIT) +#if LDBL_MANT_DIG == 64 +#define CLOSETO1(u) (u.i.m>>56 >= 0xf7) +#define CLEARBOTTOM(u) (u.i.m &= -1ULL << 32) +#elif LDBL_MANT_DIG == 113 +#define CLOSETO1(u) (u.i.top >= 0xee00) +#define CLEARBOTTOM(u) (u.i.lo = 0) +#endif long double asinl(long double x) { - union IEEEl2bits u; - long double z,r,s; - uint16_t expsign, expt; + union ldshape u = {x}; + long double z, r, s; + uint16_t e = u.i.se & 0x7fff; + int sign = u.i.se >> 15; - u.e = x; - expsign = u.xbits.expsign; - expt = expsign & 0x7fff; - if (expt >= 0x3fff) { /* |x| >= 1 or nan */ - if (expt == 0x3fff && - ((u.bits.manh&~LDBL_NBIT)|u.bits.manl) == 0) - /* asin(+-1)=+-pi/2 with inexact */ + if (e >= 0x3fff) { /* |x| >= 1 or nan */ + /* asin(+-1)=+-pi/2 with inexact */ + if (x == 1 || x == -1) return x*pio2_hi + 0x1p-120f; return 0/(x-x); } - if (expt < 0x3fff - 1) { /* |x| < 0.5 */ - if (expt < 0x3fff - 32) { /* |x|<0x1p-32, asinl(x)=x */ + if (e < 0x3fff - 1) { /* |x| < 0.5 */ + if (e < 0x3fff - (LDBL_MANT_DIG+1)/2) { /* return x with inexact if x!=0 */ FORCE_EVAL(x + 0x1p120f); return x; @@ -54,18 +56,16 @@ z = (1.0 - fabsl(x))*0.5; s = sqrtl(z); r = __invtrigl_R(z); - if (u.bits.manh >= THRESH) { /* if |x| is close to 1 */ + if (CLOSETO1(u)) { x = pio2_hi - (2*(s+s*r)-pio2_lo); } else { long double f, c; - u.e = s; - u.bits.manl = 0; - f = u.e; - c = (z-f*f)/(s+f); + u.f = s; + CLEARBOTTOM(u); + f = u.f; + c = (z - f*f)/(s + f); x = 0.5*pio2_hi-(2*s*r - (pio2_lo-2*c) - (0.5*pio2_hi-2*f)); } - if (expsign>>15) - return -x; - return x; + return sign ? -x : x; } #endif diff -Nur musl-0.9.13/src/math/atan2l.c musl-git/src/math/atan2l.c --- musl-0.9.13/src/math/atan2l.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/atan2l.c 2013-09-16 20:31:39.000000000 +0200 @@ -27,56 +27,50 @@ long double atan2l(long double y, long double x) { - union IEEEl2bits ux, uy; + union ldshape ux, uy; long double z; - int m; - uint16_t exptx, expsignx, expty, expsigny; + int m, ex, ey; if (isnan(x) || isnan(y)) return x+y; if (x == 1) return atanl(y); - uy.e = y; - expsigny = uy.xbits.expsign; - expty = expsigny & 0x7fff; - ux.e = x; - expsignx = ux.xbits.expsign; - exptx = expsignx & 0x7fff; - m = ((expsigny>>15)&1) | ((expsignx>>14)&2); /* 2*sign(x)+sign(y) */ - + ux.f = x; + uy.f = y; + ex = ux.i.se & 0x7fff; + ey = uy.i.se & 0x7fff; + m = 2*(ux.i.se>>15) | uy.i.se>>15; if (y == 0) { switch(m) { case 0: case 1: return y; /* atan(+-0,+anything)=+-0 */ - case 2: return 2*pio2_hi+0x1p-120f; /* atan(+0,-anything) = pi */ - case 3: return -2*pio2_hi-0x1p-120f; /* atan(-0,-anything) =-pi */ + case 2: return 2*pio2_hi; /* atan(+0,-anything) = pi */ + case 3: return -2*pio2_hi; /* atan(-0,-anything) =-pi */ } } if (x == 0) - return m&1 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f; - /* when x is INF */ - if (exptx == 0x7fff) { - if (expty == 0x7fff) { + return m&1 ? -pio2_hi : pio2_hi; + if (ex == 0x7fff) { + if (ey == 0x7fff) { switch(m) { - case 0: return pio2_hi*0.5+0x1p-120f; /* atan(+INF,+INF) */ - case 1: return -pio2_hi*0.5-0x1p-120f; /* atan(-INF,+INF) */ - case 2: return 1.5*pio2_hi+0x1p-120f; /* atan(+INF,-INF) */ - case 3: return -1.5*pio2_hi-0x1p-120f; /* atan(-INF,-INF) */ + case 0: return pio2_hi/2; /* atan(+INF,+INF) */ + case 1: return -pio2_hi/2; /* atan(-INF,+INF) */ + case 2: return 1.5*pio2_hi; /* atan(+INF,-INF) */ + case 3: return -1.5*pio2_hi; /* atan(-INF,-INF) */ } } else { switch(m) { case 0: return 0.0; /* atan(+...,+INF) */ case 1: return -0.0; /* atan(-...,+INF) */ - case 2: return 2*pio2_hi+0x1p-120f; /* atan(+...,-INF) */ - case 3: return -2*pio2_hi-0x1p-120f; /* atan(-...,-INF) */ + case 2: return 2*pio2_hi; /* atan(+...,-INF) */ + case 3: return -2*pio2_hi; /* atan(-...,-INF) */ } } } - /* when y is INF */ - if (exptx+120 < expty || expty == 0x7fff) - return m&1 ? -pio2_hi-0x1p-120f : pio2_hi+0x1p-120f; - - if ((m&2) && expty+120 < exptx) /* |y/x| tiny, x<0 */ + if (ex+120 < ey || ey == 0x7fff) + return m&1 ? -pio2_hi : pio2_hi; + /* z = atan(|y/x|) without spurious underflow */ + if ((m&2) && ey+120 < ex) /* |y/x| < 0x1p-120, x<0 */ z = 0.0; else z = atanl(fabsl(y/x)); diff -Nur musl-0.9.13/src/math/atanh.c musl-git/src/math/atanh.c --- musl-0.9.13/src/math/atanh.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/atanh.c 2013-09-16 20:31:39.000000000 +0200 @@ -6,16 +6,24 @@ union {double f; uint64_t i;} u = {.f = x}; unsigned e = u.i >> 52 & 0x7ff; unsigned s = u.i >> 63; + double_t y; /* |x| */ u.i &= (uint64_t)-1/2; - x = u.f; + y = u.f; if (e < 0x3ff - 1) { - /* |x| < 0.5, up to 1.7ulp error */ - x = 0.5*log1p(2*x + 2*x*x/(1-x)); + if (e < 0x3ff - 32) { + /* handle underflow */ + if (e == 0) + FORCE_EVAL((float)y); + } else { + /* |x| < 0.5, up to 1.7ulp error */ + y = 0.5*log1p(2*y + 2*y*y/(1-y)); + } } else { - x = 0.5*log1p(2*x/(1-x)); + /* avoid overflow */ + y = 0.5*log1p(2*(y/(1-y))); } - return s ? -x : x; + return s ? -y : y; } diff -Nur musl-0.9.13/src/math/atanhf.c musl-git/src/math/atanhf.c --- musl-0.9.13/src/math/atanhf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/atanhf.c 2013-09-16 20:31:39.000000000 +0200 @@ -5,16 +5,24 @@ { union {float f; uint32_t i;} u = {.f = x}; unsigned s = u.i >> 31; + float_t y; /* |x| */ u.i &= 0x7fffffff; - x = u.f; + y = u.f; if (u.i < 0x3f800000 - (1<<23)) { - /* |x| < 0.5, up to 1.7ulp error */ - x = 0.5f*log1pf(2*x + 2*x*x/(1-x)); + if (u.i < 0x3f800000 - (32<<23)) { + /* handle underflow */ + if (u.i < (1<<23)) + FORCE_EVAL((float)(y*y)); + } else { + /* |x| < 0.5, up to 1.7ulp error */ + y = 0.5f*log1pf(2*y + 2*y*y/(1-y)); + } } else { - x = 0.5f*log1pf(2*x/(1-x)); + /* avoid overflow */ + y = 0.5f*log1pf(2*(y/(1-y))); } - return s ? -x : x; + return s ? -y : y; } diff -Nur musl-0.9.13/src/math/atanhl.c musl-git/src/math/atanhl.c --- musl-0.9.13/src/math/atanhl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/atanhl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,10 +9,7 @@ /* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */ long double atanhl(long double x) { - union { - long double f; - struct{uint64_t m; uint16_t se; uint16_t pad;} i; - } u = {.f = x}; + union ldshape u = {x}; unsigned e = u.i.se & 0x7fff; unsigned s = u.i.se >> 15; @@ -20,11 +17,18 @@ u.i.se = e; x = u.f; - if (e < 0x3fff - 1) { - /* |x| < 0.5, up to 1.7ulp error */ - x = 0.5*log1pl(2*x + 2*x*x/(1-x)); + if (e < 0x3ff - 1) { + if (e < 0x3ff - LDBL_MANT_DIG/2) { + /* handle underflow */ + if (e == 0) + FORCE_EVAL((float)x); + } else { + /* |x| < 0.5, up to 1.7ulp error */ + x = 0.5*log1pl(2*x + 2*x*x/(1-x)); + } } else { - x = 0.5*log1pl(2*x/(1-x)); + /* avoid overflow */ + x = 0.5*log1pl(2*(x/(1-x))); } return s ? -x : x; } diff -Nur musl-0.9.13/src/math/atanl.c musl-git/src/math/atanl.c --- musl-0.9.13/src/math/atanl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/atanl.c 2013-09-16 20:31:39.000000000 +0200 @@ -23,6 +23,9 @@ } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +#if LDBL_MANT_DIG == 64 +#define EXPMAN(u) ((u.i.se & 0x7fff)<<8 | (u.i.m>>55 & 0xff)) + static const long double atanhi[] = { 4.63647609000806116202e-01L, 7.85398163397448309628e-01L, @@ -64,32 +67,85 @@ return aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * (aT[9] + x * aT[11])))); } +#elif LDBL_MANT_DIG == 113 +#define EXPMAN(u) ((u.i.se & 0x7fff)<<8 | u.i.top>>8) + +const long double atanhi[] = { + 4.63647609000806116214256231461214397e-01L, + 7.85398163397448309615660845819875699e-01L, + 9.82793723247329067985710611014666038e-01L, + 1.57079632679489661923132169163975140e+00L, +}; + +const long double atanlo[] = { + 4.89509642257333492668618435220297706e-36L, + 2.16795253253094525619926100651083806e-35L, + -2.31288434538183565909319952098066272e-35L, + 4.33590506506189051239852201302167613e-35L, +}; + +const long double aT[] = { + 3.33333333333333333333333333333333125e-01L, + -1.99999999999999999999999999999180430e-01L, + 1.42857142857142857142857142125269827e-01L, + -1.11111111111111111111110834490810169e-01L, + 9.09090909090909090908522355708623681e-02L, + -7.69230769230769230696553844935357021e-02L, + 6.66666666666666660390096773046256096e-02L, + -5.88235294117646671706582985209643694e-02L, + 5.26315789473666478515847092020327506e-02L, + -4.76190476189855517021024424991436144e-02L, + 4.34782608678695085948531993458097026e-02L, + -3.99999999632663469330634215991142368e-02L, + 3.70370363987423702891250829918659723e-02L, + -3.44827496515048090726669907612335954e-02L, + 3.22579620681420149871973710852268528e-02L, + -3.03020767654269261041647570626778067e-02L, + 2.85641979882534783223403715930946138e-02L, + -2.69824879726738568189929461383741323e-02L, + 2.54194698498808542954187110873675769e-02L, + -2.35083879708189059926183138130183215e-02L, + 2.04832358998165364349957325067131428e-02L, + -1.54489555488544397858507248612362957e-02L, + 8.64492360989278761493037861575248038e-03L, + -2.58521121597609872727919154569765469e-03L, +}; + +static long double T_even(long double x) +{ + return (aT[0] + x * (aT[2] + x * (aT[4] + x * (aT[6] + x * (aT[8] + + x * (aT[10] + x * (aT[12] + x * (aT[14] + x * (aT[16] + + x * (aT[18] + x * (aT[20] + x * aT[22]))))))))))); +} + +static long double T_odd(long double x) +{ + return (aT[1] + x * (aT[3] + x * (aT[5] + x * (aT[7] + x * (aT[9] + + x * (aT[11] + x * (aT[13] + x * (aT[15] + x * (aT[17] + + x * (aT[19] + x * (aT[21] + x * aT[23]))))))))))); +} +#endif long double atanl(long double x) { - union IEEEl2bits u; - long double w,s1,s2,z; + union ldshape u = {x}; + long double w, s1, s2, z; int id; - uint16_t expsign, expt; - uint32_t expman; + unsigned e = u.i.se & 0x7fff; + unsigned sign = u.i.se >> 15; + unsigned expman; - u.e = x; - expsign = u.xbits.expsign; - expt = expsign & 0x7fff; - if (expt >= 0x3fff + 65) { /* if |x| is large, atan(x)~=pi/2 */ - if (expt == 0x7fff && - ((u.bits.manh&~LDBL_NBIT)|u.bits.manl)!=0) /* NaN */ - return x+x; - z = atanhi[3] + 0x1p-120f; - return expsign>>15 ? -z : z; + if (e >= 0x3fff + LDBL_MANT_DIG + 1) { /* if |x| is large, atan(x)~=pi/2 */ + if (isnan(x)) + return x; + return sign ? -atanhi[3] : atanhi[3]; } /* Extract the exponent and the first few bits of the mantissa. */ - /* XXX There should be a more convenient way to do this. */ - expman = (expt << 8) | ((u.bits.manh >> (LDBL_MANH_SIZE - 9)) & 0xff); + expman = EXPMAN(u); if (expman < ((0x3fff - 2) << 8) + 0xc0) { /* |x| < 0.4375 */ - if (expt < 0x3fff - 32) { /* if |x| is small, atanl(x)~=x */ + if (e < 0x3fff - (LDBL_MANT_DIG+1)/2) { /* if |x| is small, atanl(x)~=x */ /* raise underflow if subnormal */ - if (expt == 0) + if (e == 0) FORCE_EVAL((float)x); return x; } @@ -108,7 +164,7 @@ if (expman < ((0x3fff + 1) << 8) + 0x38) { /* |x| < 2.4375 */ id = 2; x = (x-1.5)/(1.0+1.5*x); - } else { /* 2.4375 <= |x| < 2^ATAN_CONST */ + } else { /* 2.4375 <= |x| */ id = 3; x = -1.0/x; } @@ -123,6 +179,6 @@ if (id < 0) return x - x*(s1+s2); z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); - return expsign>>15 ? -z : z; + return sign ? -z : z; } #endif diff -Nur musl-0.9.13/src/math/cbrt.c musl-git/src/math/cbrt.c --- musl-0.9.13/src/math/cbrt.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/cbrt.c 2013-09-16 20:31:39.000000000 +0200 @@ -15,7 +15,8 @@ * Return cube root of x */ -#include "libm.h" +#include +#include static const uint32_t B1 = 715094163, /* B1 = (1023-1023/3-0.03306235651)*2**20 */ @@ -31,15 +32,10 @@ double cbrt(double x) { - int32_t hx; - union dshape u; - double r,s,t=0.0,w; - uint32_t sign; - uint32_t high,low; - - EXTRACT_WORDS(hx, low, x); - sign = hx & 0x80000000; - hx ^= sign; + union {double f; uint64_t i;} u = {x}; + double_t r,s,t,w; + uint32_t hx = u.i>>32 & 0x7fffffff; + if (hx >= 0x7ff00000) /* cbrt(NaN,INF) is itself */ return x+x; @@ -59,14 +55,16 @@ * division rounds towards minus infinity; this is also efficient. */ if (hx < 0x00100000) { /* zero or subnormal? */ - if ((hx|low) == 0) + u.f = x*0x1p54; + hx = u.i>>32 & 0x7fffffff; + if (hx == 0) return x; /* cbrt(0) is itself */ - SET_HIGH_WORD(t, 0x43500000); /* set t = 2**54 */ - t *= x; - GET_HIGH_WORD(high, t); - INSERT_WORDS(t, sign|((high&0x7fffffff)/3+B2), 0); + hx = hx/3 + B2; } else - INSERT_WORDS(t, sign|(hx/3+B1), 0); + hx = hx/3 + B1; + u.i &= 1ULL<<63; + u.i |= (uint64_t)hx << 32; + t = u.f; /* * New cbrt to 23 bits: @@ -76,7 +74,7 @@ * has produced t such than |t/cbrt(x) - 1| ~< 1/32, and cubing this * gives us bounds for r = t**3/x. * - * Try to optimize for parallel evaluation as in k_tanf.c. + * Try to optimize for parallel evaluation as in __tanf.c. */ r = (t*t)*(t/x); t = t*((P0+r*(P1+r*P2))+((r*r)*r)*(P3+r*P4)); @@ -91,9 +89,9 @@ * 0.667; the error in the rounded t can be up to about 3 23-bit ulps * before the final error is larger than 0.667 ulps. */ - u.value = t; - u.bits = (u.bits + 0x80000000) & 0xffffffffc0000000ULL; - t = u.value; + u.f = t; + u.i = (u.i + 0x80000000) & 0xffffffffc0000000ULL; + t = u.f; /* one step Newton iteration to 53 bits with error < 0.667 ulps */ s = t*t; /* t*t is exact */ diff -Nur musl-0.9.13/src/math/cbrtf.c musl-git/src/math/cbrtf.c --- musl-0.9.13/src/math/cbrtf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/cbrtf.c 2013-09-16 20:31:39.000000000 +0200 @@ -17,7 +17,8 @@ * Return cube root of x */ -#include "libm.h" +#include +#include static const unsigned B1 = 709958130, /* B1 = (127-127.0/3-0.03306235651)*2**23 */ @@ -25,15 +26,10 @@ float cbrtf(float x) { - double r,T; - float t; - int32_t hx; - uint32_t sign; - uint32_t high; - - GET_FLOAT_WORD(hx, x); - sign = hx & 0x80000000; - hx ^= sign; + double_t r,T; + union {float f; uint32_t i;} u = {x}; + uint32_t hx = u.i & 0x7fffffff; + if (hx >= 0x7f800000) /* cbrt(NaN,INF) is itself */ return x + x; @@ -41,28 +37,29 @@ if (hx < 0x00800000) { /* zero or subnormal? */ if (hx == 0) return x; /* cbrt(+-0) is itself */ - SET_FLOAT_WORD(t, 0x4b800000); /* set t = 2**24 */ - t *= x; - GET_FLOAT_WORD(high, t); - SET_FLOAT_WORD(t, sign|((high&0x7fffffff)/3+B2)); + u.f = x*0x1p24f; + hx = u.i & 0x7fffffff; + hx = hx/3 + B2; } else - SET_FLOAT_WORD(t, sign|(hx/3+B1)); + hx = hx/3 + B1; + u.i &= 0x80000000; + u.i |= hx; /* * First step Newton iteration (solving t*t-x/t == 0) to 16 bits. In * double precision so that its terms can be arranged for efficiency * without causing overflow or underflow. */ - T = t; + T = u.f; r = T*T*T; - T = T*((double)x+x+r)/(x+r+r); + T = T*((double_t)x+x+r)/(x+r+r); /* * Second step Newton iteration to 47 bits. In double precision for * efficiency and accuracy. */ r = T*T*T; - T = T*((double)x+x+r)/(x+r+r); + T = T*((double_t)x+x+r)/(x+r+r); /* rounding to 24 bits is perfect in round-to-nearest mode */ return T; diff -Nur musl-0.9.13/src/math/cbrtl.c musl-git/src/math/cbrtl.c --- musl-0.9.13/src/math/cbrtl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/cbrtl.c 2013-09-16 20:31:39.000000000 +0200 @@ -23,58 +23,50 @@ return cbrt(x); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#define BIAS (LDBL_MAX_EXP - 1) static const unsigned B1 = 709958130; /* B1 = (127-127.0/3-0.03306235651)*2**23 */ long double cbrtl(long double x) { - union IEEEl2bits u, v; + union ldshape u = {x}, v; + union {float f; uint32_t i;} uft; long double r, s, t, w; - double dr, dt, dx; - float ft, fx; - uint32_t hx; - uint16_t expsign; - int k; - - u.e = x; - expsign = u.xbits.expsign; - k = expsign & 0x7fff; + double_t dr, dt, dx; + float_t ft; + int e = u.i.se & 0x7fff; + int sign = u.i.se & 0x8000; /* * If x = +-Inf, then cbrt(x) = +-Inf. * If x = NaN, then cbrt(x) = NaN. */ - if (k == BIAS + LDBL_MAX_EXP) + if (e == 0x7fff) return x + x; - - if (k == 0) { + if (e == 0) { + /* Adjust subnormal numbers. */ + u.f *= 0x1p120; + e = u.i.se & 0x7fff; /* If x = +-0, then cbrt(x) = +-0. */ - if ((u.bits.manh | u.bits.manl) == 0) + if (e == 0) return x; - /* Adjust subnormal numbers. */ - u.e *= 0x1.0p514; - k = u.bits.exp; - k -= BIAS + 514; - } else - k -= BIAS; - u.xbits.expsign = BIAS; - v.e = 1; - - x = u.e; - switch (k % 3) { + e -= 120; + } + e -= 0x3fff; + u.i.se = 0x3fff; + x = u.f; + switch (e % 3) { case 1: case -2: - x = 2*x; - k--; + x *= 2; + e--; break; case 2: case -1: - x = 4*x; - k -= 2; + x *= 4; + e -= 2; break; } - v.xbits.expsign = (expsign & 0x8000) | (BIAS + k / 3); + v.f = 1.0; + v.i.se = sign | (0x3fff + e/3); /* * The following is the guts of s_cbrtf, with the handling of @@ -83,9 +75,9 @@ */ /* ~5-bit estimate: */ - fx = x; - GET_FLOAT_WORD(hx, fx); - SET_FLOAT_WORD(ft, ((hx & 0x7fffffff) / 3 + B1)); + uft.f = x; + uft.i = (uft.i & 0x7fffffff)/3 + B1; + ft = uft.f; /* ~16-bit estimate: */ dx = x; @@ -126,7 +118,7 @@ r = (r-t)/(w+r); /* r-t is exact; w+r ~= 3*t */ t = t+t*r; /* error <= 0.5 + 0.5/3 + epsilon */ - t *= v.e; + t *= v.f; return t; } #endif diff -Nur musl-0.9.13/src/math/ceil.c musl-git/src/math/ceil.c --- musl-0.9.13/src/math/ceil.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/ceil.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,82 +1,24 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_ceil.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * ceil(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to ceil(x). - */ - #include "libm.h" -static const double huge = 1.0e300; - double ceil(double x) { - int32_t i0,i1,j0; - uint32_t i,j; + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double_t y; - EXTRACT_WORDS(i0, i1, x); - // FIXME signed shift - j0 = ((i0>>20)&0x7ff) - 0x3ff; - if (j0 < 20) { - if (j0 < 0) { - /* raise inexact if x != 0 */ - if (huge+x > 0.0) { - if (i0 < 0) { - i0 = 0x80000000; - i1=0; - } else if ((i0|i1) != 0) { - i0=0x3ff00000; - i1=0; - } - } - } else { - i = 0x000fffff>>j0; - if (((i0&i)|i1) == 0) /* x is integral */ - return x; - /* raise inexact flag */ - if (huge+x > 0.0) { - if (i0 > 0) - i0 += 0x00100000>>j0; - i0 &= ~i; - i1 = 0; - } - } - } else if (j0 > 51) { - if (j0 == 0x400) /* inf or NaN */ - return x+x; - return x; /* x is integral */ - } else { - i = (uint32_t)0xffffffff>>(j0-20); - if ((i1&i) == 0) - return x; /* x is integral */ - /* raise inexact flag */ - if (huge+x > 0.0) { - if (i0 > 0) { - if (j0 == 20) - i0 += 1; - else { - j = i1 + (1<<(52-j0)); - if (j < i1) /* got a carry */ - i0 += 1; - i1 = j; - } - } - i1 &= ~i; - } + if (e >= 0x3ff+52 || x == 0) + return x; + /* y = int(x) - x, where int(x) is an integer neighbor of x */ + if (u.i >> 63) + y = (double)(x - 0x1p52) + 0x1p52 - x; + else + y = (double)(x + 0x1p52) - 0x1p52 - x; + /* special case because of non-nearest rounding modes */ + if (e <= 0x3ff-1) { + FORCE_EVAL(y); + return u.i >> 63 ? -0.0 : 1; } - INSERT_WORDS(x, i0, i1); - return x; + if (y < 0) + return x + y + 1; + return x + y; } diff -Nur musl-0.9.13/src/math/ceilf.c musl-git/src/math/ceilf.c --- musl-0.9.13/src/math/ceilf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/ceilf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,54 +1,27 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_ceilf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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 "libm.h" -static const float huge = 1.0e30; - float ceilf(float x) { - int32_t i0,j0; - uint32_t i; + union {float f; uint32_t i;} u = {x}; + int e = (int)(u.i >> 23 & 0xff) - 0x7f; + uint32_t m; - GET_FLOAT_WORD(i0, x); - j0 = ((i0>>23)&0xff) - 0x7f; - if (j0 < 23) { - if (j0 < 0) { - /* raise inexact if x != 0 */ - if (huge+x > 0.0f) { - if (i0 < 0) - i0 = 0x80000000; - else if(i0 != 0) - i0 = 0x3f800000; - } - } else { - i = 0x007fffff>>j0; - if ((i0&i) == 0) - return x; /* x is integral */ - /* raise inexact flag */ - if (huge+x > 0.0f) { - if (i0 > 0) - i0 += 0x00800000>>j0; - i0 &= ~i; - } - } + if (e >= 23) + return x; + if (e >= 0) { + m = 0x007fffff >> e; + if ((u.i & m) == 0) + return x; + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31 == 0) + u.i += m; + u.i &= ~m; } else { - if (j0 == 0x80) /* inf or NaN */ - return x+x; - return x; /* x is integral */ + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31) + u.f = -0.0; + else if (u.i << 1) + u.f = 1.0; } - SET_FLOAT_WORD(x, i0); - return x; + return u.f; } diff -Nur musl-0.9.13/src/math/ceill.c musl-git/src/math/ceill.c --- musl-0.9.13/src/math/ceill.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/ceill.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,23 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_ceill.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * ceill(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to ceill(x). - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -26,77 +6,31 @@ return ceil(x); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#ifdef LDBL_IMPLICIT_NBIT -#define MANH_SIZE (LDBL_MANH_SIZE + 1) -#define INC_MANH(u, c) do { \ - uint64_t o = u.bits.manh; \ - u.bits.manh += (c); \ - if (u.bits.manh < o) \ - u.bits.exp++; \ -} while (0) -#else -#define MANH_SIZE LDBL_MANH_SIZE -#define INC_MANH(u, c) do { \ - uint64_t o = u.bits.manh; \ - u.bits.manh += (c); \ - if (u.bits.manh < o) { \ - u.bits.exp++; \ - u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \ - } \ -} while (0) +#if LDBL_MANT_DIG == 64 +#define TOINT 0x1p63 +#elif LDBL_MANT_DIG == 113 +#define TOINT 0x1p112 #endif - -static const long double huge = 1.0e300; - long double ceill(long double x) { - union IEEEl2bits u = { .e = x }; - int e = u.bits.exp - LDBL_MAX_EXP + 1; - - if (e < MANH_SIZE - 1) { - if (e < 0) { - /* raise inexact if x != 0 */ - if (huge + x > 0.0) - if (u.bits.exp > 0 || - (u.bits.manh | u.bits.manl) != 0) - u.e = u.bits.sign ? -0.0 : 1.0; - } else { - uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); - if (((u.bits.manh & m) | u.bits.manl) == 0) - return x; /* x is integral */ - if (!u.bits.sign) { -#ifdef LDBL_IMPLICIT_NBIT - if (e == 0) - u.bits.exp++; - else -#endif - INC_MANH(u, 1llu << (MANH_SIZE - e - 1)); - } - /* raise inexact flag */ - if (huge + x > 0.0) { - u.bits.manh &= ~m; - u.bits.manl = 0; - } - } - } else if (e < LDBL_MANT_DIG - 1) { - uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); - if ((u.bits.manl & m) == 0) - return x; /* x is integral */ - if (!u.bits.sign) { - if (e == MANH_SIZE - 1) - INC_MANH(u, 1); - else { - uint64_t o = u.bits.manl; - u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1); - if (u.bits.manl < o) /* got a carry */ - INC_MANH(u, 1); - } - } - /* raise inexact flag */ - if (huge + x > 0.0) - u.bits.manl &= ~m; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + long double y; + + if (e >= 0x3fff+LDBL_MANT_DIG-1 || x == 0) + return x; + /* y = int(x) - x, where int(x) is an integer neighbor of x */ + if (u.i.se >> 15) + y = x - TOINT + TOINT - x; + else + y = x + TOINT - TOINT - x; + /* special case because of non-nearest rounding modes */ + if (e <= 0x3fff-1) { + FORCE_EVAL(y); + return u.i.se >> 15 ? -0.0 : 1; } - return u.e; + if (y < 0) + return x + y + 1; + return x + y; } #endif diff -Nur musl-0.9.13/src/math/copysign.c musl-git/src/math/copysign.c --- musl-0.9.13/src/math/copysign.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/copysign.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,11 +1,8 @@ #include "libm.h" double copysign(double x, double y) { - union dshape ux, uy; - - ux.value = x; - uy.value = y; - ux.bits &= (uint64_t)-1>>1; - ux.bits |= uy.bits & (uint64_t)1<<63; - return ux.value; + union {double f; uint64_t i;} ux={x}, uy={y}; + ux.i &= -1ULL/2; + ux.i |= uy.i & 1ULL<<63; + return ux.f; } diff -Nur musl-0.9.13/src/math/copysignf.c musl-git/src/math/copysignf.c --- musl-0.9.13/src/math/copysignf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/copysignf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,11 +1,10 @@ -#include "libm.h" +#include +#include -float copysignf(float x, float y) { - union fshape ux, uy; - - ux.value = x; - uy.value = y; - ux.bits &= (uint32_t)-1>>1; - ux.bits |= uy.bits & (uint32_t)1<<31; - return ux.value; +float copysignf(float x, float y) +{ + union {float f; uint32_t i;} ux={x}, uy={y}; + ux.i &= 0x7fffffff; + ux.i |= uy.i & 0x80000000; + return ux.f; } diff -Nur musl-0.9.13/src/math/copysignl.c musl-git/src/math/copysignl.c --- musl-0.9.13/src/math/copysignl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/copysignl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,8 +9,8 @@ long double copysignl(long double x, long double y) { union ldshape ux = {x}, uy = {y}; - - ux.bits.sign = uy.bits.sign; - return ux.value; + ux.i.se &= 0x7fff; + ux.i.se |= uy.i.se & 0x8000; + return ux.f; } #endif diff -Nur musl-0.9.13/src/math/coshl.c musl-git/src/math/coshl.c --- musl-0.9.13/src/math/coshl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/coshl.c 2013-09-16 20:31:39.000000000 +0200 @@ -8,10 +8,7 @@ #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 long double coshl(long double x) { - union { - long double f; - struct{uint64_t m; uint16_t se; uint16_t pad;} i; - } u = {.f = x}; + union ldshape u = {x}; unsigned ex = u.i.se & 0x7fff; uint32_t w; long double t; diff -Nur musl-0.9.13/src/math/cosl.c musl-git/src/math/cosl.c --- musl-0.9.13/src/math/cosl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/cosl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,34 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_cosl.c */ -/*- - * Copyright (c) 2007 Steven G. Kargl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Limited testing on pseudorandom numbers drawn within [-2e8:4e8] shows - * an accuracy of <= 0.7412 ULP. - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -38,44 +7,33 @@ #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 long double cosl(long double x) { - union IEEEl2bits z; + union ldshape u = {x}; unsigned n; - long double y[2]; - long double hi, lo; - - z.e = x; - z.bits.sign = 0; + long double y[2], hi, lo; - /* If x = NaN or Inf, then cos(x) = NaN. */ - if (z.bits.exp == 0x7fff) - return (x - x) / (x - x); - - /* |x| < (double)pi/4 */ - if (z.e < M_PI_4) { - /* |x| < 0x1p-64 */ - if (z.bits.exp < 0x3fff - 64) + u.i.se &= 0x7fff; + if (u.i.se == 0x7fff) + return x - x; + x = u.f; + if (x < M_PI_4) { + if (u.i.se < 0x3fff - LDBL_MANT_DIG) /* raise inexact if x!=0 */ return 1.0 + x; - return __cosl(z.e, 0); + return __cosl(x, 0); } - n = __rem_pio2l(x, y); hi = y[0]; lo = y[1]; switch (n & 3) { case 0: - hi = __cosl(hi, lo); - break; + return __cosl(hi, lo); case 1: - hi = -__sinl(hi, lo, 1); - break; + return -__sinl(hi, lo, 1); case 2: - hi = -__cosl(hi, lo); - break; + return -__cosl(hi, lo); case 3: - hi = __sinl(hi, lo, 1); - break; + default: + return __sinl(hi, lo, 1); } - return hi; } #endif diff -Nur musl-0.9.13/src/math/erfl.c musl-git/src/math/erfl.c --- musl-0.9.13/src/math/erfl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/erfl.c 2013-09-16 20:31:39.000000000 +0200 @@ -253,8 +253,8 @@ static long double erfc2(uint32_t ix, long double x) { + union ldshape u; long double s,z,R,S; - uint32_t i0,i1; if (ix < 0x3fffa000) /* 0.84375 <= |x| < 1.25 */ return erfc1(x); @@ -288,28 +288,22 @@ S = sc[0] + s * (sc[1] + s * (sc[2] + s * (sc[3] + s * (sc[4] + s)))); } - z = x; - GET_LDOUBLE_WORDS(ix, i0, i1, z); - i1 = 0; - i0 &= 0xffffff00; - SET_LDOUBLE_WORDS(z, ix, i0, i1); + u.f = x; + u.i.m &= -1ULL << 40; + z = u.f; return expl(-z*z - 0.5625) * expl((z - x) * (z + x) + R / S) / x; } long double erfl(long double x) { long double r, s, z, y; - uint32_t i0, i1, ix; - int sign; + union ldshape u = {x}; + uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48; + int sign = u.i.se >> 15; - GET_LDOUBLE_WORDS(ix, i0, i1, x); - sign = ix >> 15; - ix &= 0x7fff; - if (ix == 0x7fff) { + if (ix >= 0x7fff0000) /* erf(nan)=nan, erf(+-inf)=+-1 */ return 1 - 2*sign + 1/x; - } - ix = (ix << 16) | (i0 >> 16); if (ix < 0x3ffed800) { /* |x| < 0.84375 */ if (ix < 0x3fde8000) { /* |x| < 2**-33 */ return 0.125 * (8 * x + efx8 * x); /* avoid underflow */ @@ -332,17 +326,13 @@ long double erfcl(long double x) { long double r, s, z, y; - uint32_t i0, i1, ix; - int sign; + union ldshape u = {x}; + uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48; + int sign = u.i.se >> 15; - GET_LDOUBLE_WORDS(ix, i0, i1, x); - sign = ix>>15; - ix &= 0x7fff; - if (ix == 0x7fff) + if (ix >= 0x7fff0000) /* erfc(nan) = nan, erfc(+-inf) = 0,2 */ return 2*sign + 1/x; - - ix = (ix << 16) | (i0 >> 16); if (ix < 0x3ffed800) { /* |x| < 0.84375 */ if (ix < 0x3fbe0000) /* |x| < 2**-65 */ return 1.0 - x; @@ -358,6 +348,7 @@ } if (ix < 0x4005d600) /* |x| < 107 */ return sign ? 2 - erfc2(ix,x) : erfc2(ix,x); - return sign ? 2 - 0x1p-16382L : 0x1p-16382L*0x1p-16382L; + y = 0x1p-16382L; + return sign ? 2 - y : y*y; } #endif diff -Nur musl-0.9.13/src/math/exp.c musl-git/src/math/exp.c --- musl-0.9.13/src/math/exp.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/exp.c 2013-09-16 20:31:39.000000000 +0200 @@ -80,7 +80,7 @@ double exp(double x) { - double hi, lo, c, xx; + double_t hi, lo, c, xx, y; int k, sign; uint32_t hx; @@ -89,20 +89,19 @@ hx &= 0x7fffffff; /* high word of |x| */ /* special cases */ - if (hx >= 0x40862e42) { /* if |x| >= 709.78... */ + if (hx >= 0x4086232b) { /* if |x| >= 708.39... */ if (isnan(x)) return x; - if (hx == 0x7ff00000 && sign) /* -inf */ - return 0; if (x > 709.782712893383973096) { /* overflow if x!=inf */ - STRICT_ASSIGN(double, x, 0x1p1023 * x); + x *= 0x1p1023; return x; } - if (x < -745.13321910194110842) { - /* underflow */ - STRICT_ASSIGN(double, x, 0x1p-1000 * 0x1p-1000); - return x; + if (x < -708.39641853226410622) { + /* underflow if x!=-inf */ + FORCE_EVAL((float)(-0x1p-149/x)); + if (x < -745.13321910194110842) + return 0; } } @@ -114,7 +113,7 @@ k = 1 - sign - sign; hi = x - k*ln2hi; /* k*ln2hi is exact here */ lo = k*ln2lo; - STRICT_ASSIGN(double, x, hi - lo); + x = hi - lo; } else if (hx > 0x3e300000) { /* if |x| > 2**-28 */ k = 0; hi = x; @@ -128,8 +127,8 @@ /* x is now in primary range */ xx = x*x; c = x - xx*(P1+xx*(P2+xx*(P3+xx*(P4+xx*P5)))); - x = 1 + (x*c/(2-c) - lo + hi); + y = 1 + (x*c/(2-c) - lo + hi); if (k == 0) - return x; - return scalbn(x, k); + return y; + return scalbn(y, k); } diff -Nur musl-0.9.13/src/math/exp2.c musl-git/src/math/exp2.c --- musl-0.9.13/src/math/exp2.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/exp2.c 2013-09-16 20:31:39.000000000 +0200 @@ -305,7 +305,7 @@ * Method: (accurate tables) * * Reduce x: - * x = 2**k + y, for integer k and |y| <= 1/2. + * x = k + y, for integer k and |y| <= 1/2. * Thus we have exp2(x) = 2**k * exp2(y). * * Reduce y: @@ -330,41 +330,41 @@ */ double exp2(double x) { - double r, t, z; - uint32_t hx, ix, i0; + double_t r, t, z; + uint32_t ix, i0; + union {double f; uint64_t i;} u = {x}; union {uint32_t u; int32_t i;} k; /* Filter out exceptional cases. */ - GET_HIGH_WORD(hx, x); - ix = hx & 0x7fffffff; - if (ix >= 0x40900000) { /* |x| >= 1024 */ - if (ix >= 0x7ff00000) { - GET_LOW_WORD(ix, x); - if (hx == 0xfff00000 && ix == 0) /* -inf */ - return 0; - return x; - } - if (x >= 1024) { - STRICT_ASSIGN(double, x, x * 0x1p1023); + ix = u.i>>32 & 0x7fffffff; + if (ix >= 0x408ff000) { /* |x| >= 1022 or nan */ + if (ix >= 0x40900000 && u.i>>63 == 0) { /* x >= 1024 or nan */ + /* overflow */ + x *= 0x1p1023; return x; } - if (x <= -1075) { - STRICT_ASSIGN(double, x, 0x1p-1000*0x1p-1000); - return x; + if (ix >= 0x7ff00000) /* -inf or -nan */ + return -1/x; + if (u.i>>63) { /* x <= -1022 */ + /* underflow */ + if (x <= -1075 || x - 0x1p52 + 0x1p52 != x) + FORCE_EVAL((float)(-0x1p-149/x)); + if (x <= -1075) + return 0; } } else if (ix < 0x3c900000) { /* |x| < 0x1p-54 */ return 1.0 + x; } /* Reduce x, computing z, i0, and k. */ - STRICT_ASSIGN(double, t, x + redux); - GET_LOW_WORD(i0, t); + u.f = x + redux; + i0 = u.i; i0 += TBLSIZE / 2; k.u = i0 / TBLSIZE * TBLSIZE; k.i /= TBLSIZE; i0 %= TBLSIZE; - t -= redux; - z = x - t; + u.f -= redux; + z = x - u.f; /* Compute r = exp2(y) = exp2t[i0] * p(z - eps[i]). */ t = tbl[2*i0]; /* exp2t[i0] */ diff -Nur musl-0.9.13/src/math/exp2f.c musl-git/src/math/exp2f.c --- musl-0.9.13/src/math/exp2f.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/exp2f.c 2013-09-16 20:31:39.000000000 +0200 @@ -63,7 +63,7 @@ * Method: (equally-spaced tables) * * Reduce x: - * x = 2**k + y, for integer k and |y| <= 1/2. + * x = k + y, for integer k and |y| <= 1/2. * Thus we have exp2f(x) = 2**k * exp2(y). * * Reduce y: @@ -83,46 +83,42 @@ */ float exp2f(float x) { - double tv, twopk, u, z; - float t; - uint32_t hx, ix, i0, k; + double_t t, r, z; + union {float f; uint32_t i;} u = {x}; + union {double f; uint64_t i;} uk; + uint32_t ix, i0, k; /* Filter out exceptional cases. */ - GET_FLOAT_WORD(hx, x); - ix = hx & 0x7fffffff; - if (ix >= 0x43000000) { /* |x| >= 128 */ - if (ix >= 0x7f800000) { - if (hx == 0xff800000) /* -inf */ - return 0; - return x; - } - if (x >= 128) { - STRICT_ASSIGN(float, x, x * 0x1p127f); + ix = u.i & 0x7fffffff; + if (ix > 0x42fc0000) { /* |x| > 126 */ + if (u.i >= 0x43000000 && u.i < 0x80000000) { /* x >= 128 */ + x *= 0x1p127f; return x; } - if (x <= -150) { - STRICT_ASSIGN(float, x, 0x1p-100f*0x1p-100f); - return x; + if (u.i >= 0x80000000) { /* x < -126 */ + if (u.i >= 0xc3160000 || (u.i & 0x0000ffff)) + FORCE_EVAL(-0x1p-149f/x); + if (u.i >= 0xc3160000) /* x <= -150 */ + return 0; } } else if (ix <= 0x33000000) { /* |x| <= 0x1p-25 */ return 1.0f + x; } /* Reduce x, computing z, i0, and k. */ - STRICT_ASSIGN(float, t, x + redux); - GET_FLOAT_WORD(i0, t); + u.f = x + redux; + i0 = u.i; i0 += TBLSIZE / 2; - k = (i0 / TBLSIZE) << 20; + k = i0 / TBLSIZE; + uk.i = (uint64_t)(0x3ff + k)<<52; i0 &= TBLSIZE - 1; - t -= redux; - z = x - t; - INSERT_WORDS(twopk, 0x3ff00000 + k, 0); - + u.f -= redux; + z = x - u.f; /* Compute r = exp2(y) = exp2ft[i0] * p(z). */ - tv = exp2ft[i0]; - u = tv * z; - tv = tv + u * (P1 + z * P2) + u * (z * z) * (P3 + z * P4); + r = exp2ft[i0]; + t = r * z; + r = r + t * (P1 + z * P2) + t * (z * z) * (P3 + z * P4); - /* Scale by 2**(k>>20). */ - return tv * twopk; + /* Scale by 2**k */ + return r * uk.f; } diff -Nur musl-0.9.13/src/math/exp2l.c musl-git/src/math/exp2l.c --- musl-0.9.13/src/math/exp2l.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/exp2l.c 2013-09-16 20:31:39.000000000 +0200 @@ -33,13 +33,9 @@ return exp2(x); } #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 - #define TBLBITS 7 #define TBLSIZE (1 << TBLBITS) -#define BIAS (LDBL_MAX_EXP - 1) -#define EXPMASK (BIAS + LDBL_MAX_EXP) - static const double redux = 0x1.8p63 / TBLSIZE, P1 = 0x1.62e42fefa39efp-1, @@ -203,29 +199,29 @@ */ long double exp2l(long double x) { - union IEEEl2bits u, v; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; long double r, z; - uint32_t hx, ix, i0; + uint32_t i0; union {uint32_t u; int32_t i;} k; /* Filter out exceptional cases. */ - u.e = x; - hx = u.xbits.expsign; - ix = hx & EXPMASK; - if (ix >= BIAS + 14) { /* |x| >= 16384 or x is NaN */ - if (ix == EXPMASK) { - if (u.xbits.man == 1ULL << 63 && hx == 0xffff) /* -inf */ + if (e >= 0x3fff + 13) { /* |x| >= 8192 or x is NaN */ + if (u.i.se >= 0x3fff + 14 && u.i.se >> 15 == 0) + /* overflow */ + return x * 0x1p16383L; + if (e == 0x7fff) /* -inf or -nan */ + return -1/x; + if (x < -16382) { + if (x <= -16446 || x - 0x1p63 + 0x1p63 != x) + /* underflow */ + FORCE_EVAL((float)(-0x1p-149/x)); + if (x <= -16446) return 0; - return x; - } - if (x >= 16384) { - x *= 0x1p16383L; - return x; } - if (x <= -16446) - return 0x1p-10000L*0x1p-10000L; - } else if (ix < BIAS - 64) /* |x| < 0x1p-64 */ + } else if (e < 0x3fff - 64) { return 1 + x; + } /* * Reduce x, computing z, i0, and k. The low bits of x + redux @@ -238,13 +234,13 @@ * We split this into k = 0xabc and i0 = 0x12 (adjusted to * index into the table), then we compute z = 0x0.003456p0. */ - u.e = x + redux; - i0 = u.bits.manl + TBLSIZE / 2; + u.f = x + redux; + i0 = u.i.m + TBLSIZE / 2; k.u = i0 / TBLSIZE * TBLSIZE; k.i /= TBLSIZE; i0 %= TBLSIZE; - u.e -= redux; - z = x - u.e; + u.f -= redux; + z = x - u.f; /* Compute r = exp2l(y) = exp2lt[i0] * p(z). */ long double t_hi = tbl[2*i0]; diff -Nur musl-0.9.13/src/math/expf.c musl-git/src/math/expf.c --- musl-0.9.13/src/math/expf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/expf.c 2013-09-16 20:31:39.000000000 +0200 @@ -29,7 +29,7 @@ float expf(float x) { - float hi, lo, c, xx; + float_t hi, lo, c, xx, y; int k, sign; uint32_t hx; @@ -38,20 +38,17 @@ hx &= 0x7fffffff; /* high word of |x| */ /* special cases */ - if (hx >= 0x42b17218) { /* if |x| >= 88.722839f or NaN */ - if (hx > 0x7f800000) /* NaN */ - return x; - if (!sign) { - /* overflow if x!=inf */ - STRICT_ASSIGN(float, x, x * 0x1p127f); + if (hx >= 0x42aeac50) { /* if |x| >= -87.33655f or NaN */ + if (hx >= 0x42b17218 && !sign) { /* x >= 88.722839f */ + /* overflow */ + x *= 0x1p127f; return x; } - if (hx == 0x7f800000) /* -inf */ - return 0; - if (hx >= 0x42cff1b5) { /* x <= -103.972084f */ + if (sign) { /* underflow */ - STRICT_ASSIGN(float, x, 0x1p-100f*0x1p-100f); - return x; + FORCE_EVAL(-0x1p-149f/x); + if (hx >= 0x42cff1b5) /* x <= -103.972084f */ + return 0; } } @@ -63,7 +60,7 @@ k = 1 - sign - sign; hi = x - k*ln2hi; /* k*ln2hi is exact here */ lo = k*ln2lo; - STRICT_ASSIGN(float, x, hi - lo); + x = hi - lo; } else if (hx > 0x39000000) { /* |x| > 2**-14 */ k = 0; hi = x; @@ -77,8 +74,8 @@ /* x is now in primary range */ xx = x*x; c = x - xx*(P1+xx*P2); - x = 1 + (x*c/(2-c) - lo + hi); + y = 1 + (x*c/(2-c) - lo + hi); if (k == 0) - return x; - return scalbnf(x, k); + return y; + return scalbnf(y, k); } diff -Nur musl-0.9.13/src/math/expl.c musl-git/src/math/expl.c --- musl-0.9.13/src/math/expl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/expl.c 2013-09-16 20:31:39.000000000 +0200 @@ -100,7 +100,7 @@ if (x > 11356.5234062941439488L) /* x > ln(2^16384 - 0.5) */ return x * 0x1p16383L; if (x < -11399.4985314888605581L) /* x < ln(2^-16446) */ - return 0x1p-10000L * 0x1p-10000L; + return -0x1p-16445L/x; /* Express e**x = e**f 2**k * = e**(f + k ln(2)) diff -Nur musl-0.9.13/src/math/expm1.c musl-git/src/math/expm1.c --- musl-0.9.13/src/math/expm1.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/expm1.c 2013-09-16 20:31:39.000000000 +0200 @@ -31,7 +31,7 @@ * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... - * We use a special Reme algorithm on [0,0.347] to generate + * We use a special Remez algorithm on [0,0.347] to generate * a polynomial of degree 5 in r*r to approximate R1. The * maximum error of this polynomial approximation is bounded * by 2**-61. In other words, @@ -107,8 +107,6 @@ #include "libm.h" static const double -huge = 1.0e+300, -tiny = 1.0e-300, o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ ln2_hi = 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ ln2_lo = 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ @@ -122,39 +120,27 @@ double expm1(double x) { - double y,hi,lo,c,t,e,hxs,hfx,r1,twopk; - int32_t k,xsb; - uint32_t hx; - - GET_HIGH_WORD(hx, x); - xsb = hx&0x80000000; /* sign bit of x */ - hx &= 0x7fffffff; /* high word of |x| */ + double_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk; + union {double f; uint64_t i;} u = {x}; + uint32_t hx = u.i>>32 & 0x7fffffff; + int k, sign = u.i>>63; /* filter out huge and non-finite argument */ if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */ - if (hx >= 0x40862E42) { /* if |x|>=709.78... */ - if (hx >= 0x7ff00000) { - uint32_t low; - - GET_LOW_WORD(low, x); - if (((hx&0xfffff)|low) != 0) /* NaN */ - return x+x; - return xsb==0 ? x : -1.0; /* exp(+-inf)={inf,-1} */ - } - if(x > o_threshold) - return huge*huge; /* overflow */ - } - if (xsb != 0) { /* x < -56*ln2, return -1.0 with inexact */ - /* raise inexact */ - if(x+tiny<0.0) - return tiny-1.0; /* return -1 */ + if (isnan(x)) + return x; + if (sign) + return -1; + if (x > o_threshold) { + x *= 0x1p1023; + return x; } } /* argument reduction */ if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ - if (xsb == 0) { + if (!sign) { hi = x - ln2_hi; lo = ln2_lo; k = 1; @@ -164,17 +150,17 @@ k = -1; } } else { - k = invln2*x + (xsb==0 ? 0.5 : -0.5); + k = invln2*x + (sign ? -0.5 : 0.5); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } - STRICT_ASSIGN(double, x, hi - lo); + x = hi-lo; c = (hi-x)-lo; } else if (hx < 0x3c900000) { /* |x| < 2**-54, return x */ - /* raise inexact flags when x != 0 */ - t = huge+x; - return x - (t-(huge+x)); + if (hx < 0x00100000) + FORCE_EVAL((float)x); + return x; } else k = 0; @@ -186,9 +172,9 @@ e = hxs*((r1-t)/(6.0 - x*t)); if (k == 0) /* c is 0 */ return x - (x*e-hxs); - INSERT_WORDS(twopk, 0x3ff00000+(k<<20), 0); /* 2^k */ e = x*(e-c) - c; e -= hxs; + /* exp(x) ~ 2^k (x_reduced - e + 1) */ if (k == -1) return 0.5*(x-e) - 0.5; if (k == 1) { @@ -196,24 +182,20 @@ return -2.0*(e-(x+0.5)); return 1.0+2.0*(x-e); } - if (k <= -2 || k > 56) { /* suffice to return exp(x)-1 */ - y = 1.0 - (e-x); + u.i = (uint64_t)(0x3ff + k)<<52; /* 2^k */ + twopk = u.f; + if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ + y = x - e + 1.0; if (k == 1024) y = y*2.0*0x1p1023; else y = y*twopk; return y - 1.0; } - t = 1.0; - if (k < 20) { - SET_HIGH_WORD(t, 0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */ - y = t-(e-x); - y = y*twopk; - } else { - SET_HIGH_WORD(t, ((0x3ff-k)<<20)); /* 2^-k */ - y = x-(e+t); - y += 1.0; - y = y*twopk; - } + u.i = (uint64_t)(0x3ff - k)<<52; /* 2^-k */ + if (k < 20) + y = (x-e+(1-u.f))*twopk; + else + y = (x-(e+u.f)+1)*twopk; return y; } diff -Nur musl-0.9.13/src/math/expm1f.c musl-git/src/math/expm1f.c --- musl-0.9.13/src/math/expm1f.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/expm1f.c 2013-09-16 20:31:39.000000000 +0200 @@ -16,8 +16,6 @@ #include "libm.h" static const float -huge = 1.0e+30, -tiny = 1.0e-30, o_threshold = 8.8721679688e+01, /* 0x42b17180 */ ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ @@ -32,35 +30,27 @@ float expm1f(float x) { - float y,hi,lo,c,t,e,hxs,hfx,r1,twopk; - int32_t k,xsb; - uint32_t hx; - - GET_FLOAT_WORD(hx, x); - xsb = hx&0x80000000; /* sign bit of x */ - hx &= 0x7fffffff; /* high word of |x| */ + float_t y,hi,lo,c,t,e,hxs,hfx,r1,twopk; + union {float f; uint32_t i;} u = {x}; + uint32_t hx = u.i & 0x7fffffff; + int k, sign = u.i >> 31; /* filter out huge and non-finite argument */ if (hx >= 0x4195b844) { /* if |x|>=27*ln2 */ - if (hx >= 0x42b17218) { /* if |x|>=88.721... */ - if (hx > 0x7f800000) /* NaN */ - return x+x; - if (hx == 0x7f800000) /* exp(+-inf)={inf,-1} */ - return xsb==0 ? x : -1.0; - if (x > o_threshold) - return huge*huge; /* overflow */ - } - if (xsb != 0) { /* x < -27*ln2 */ - /* raise inexact */ - if (x+tiny < 0.0f) - return tiny-1.0f; /* return -1 */ + if (hx > 0x7f800000) /* NaN */ + return x; + if (sign) + return -1; + if (x > o_threshold) { + x *= 0x1p127f; + return x; } } /* argument reduction */ if (hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */ if (hx < 0x3F851592) { /* and |x| < 1.5 ln2 */ - if (xsb == 0) { + if (!sign) { hi = x - ln2_hi; lo = ln2_lo; k = 1; @@ -70,16 +60,17 @@ k = -1; } } else { - k = invln2*x + (xsb==0 ? 0.5f : -0.5f); + k = invln2*x + (sign ? -0.5f : 0.5f); t = k; hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ lo = t*ln2_lo; } - STRICT_ASSIGN(float, x, hi - lo); + x = hi-lo; c = (hi-x)-lo; } else if (hx < 0x33000000) { /* when |x|<2**-25, return x */ - t = huge+x; /* return x with inexact flags when x!=0 */ - return x - (t-(huge+x)); + if (hx < 0x00800000) + FORCE_EVAL(x*x); + return x; } else k = 0; @@ -91,9 +82,9 @@ e = hxs*((r1-t)/(6.0f - x*t)); if (k == 0) /* c is 0 */ return x - (x*e-hxs); - SET_FLOAT_WORD(twopk, 0x3f800000+(k<<23)); /* 2^k */ e = x*(e-c) - c; e -= hxs; + /* exp(x) ~ 2^k (x_reduced - e + 1) */ if (k == -1) return 0.5f*(x-e) - 0.5f; if (k == 1) { @@ -101,24 +92,20 @@ return -2.0f*(e-(x+0.5f)); return 1.0f + 2.0f*(x-e); } - if (k <= -2 || k > 56) { /* suffice to return exp(x)-1 */ - y = 1.0f - (e - x); + u.i = (0x7f+k)<<23; /* 2^k */ + twopk = u.f; + if (k < 0 || k > 56) { /* suffice to return exp(x)-1 */ + y = x - e + 1.0f; if (k == 128) y = y*2.0f*0x1p127f; else y = y*twopk; return y - 1.0f; } - t = 1.0f; - if (k < 23) { - SET_FLOAT_WORD(t, 0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */ - y = t - (e - x); - y = y*twopk; - } else { - SET_FLOAT_WORD(t, (0x7f-k)<<23); /* 2^-k */ - y = x - (e + t); - y += 1.0f; - y = y*twopk; - } + u.i = (0x7f-k)<<23; /* 2^-k */ + if (k < 23) + y = (x-e+(1-u.f))*twopk; + else + y = (x-(e+u.f)+1)*twopk; return y; } diff -Nur musl-0.9.13/src/math/fabs.c musl-git/src/math/fabs.c --- musl-0.9.13/src/math/fabs.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fabs.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,9 @@ -#include "libm.h" +#include +#include double fabs(double x) { - union dshape u; - - u.value = x; - u.bits &= (uint64_t)-1 / 2; - return u.value; + union {double f; uint64_t i;} u = {x}; + u.i &= -1ULL/2; + return u.f; } diff -Nur musl-0.9.13/src/math/fabsf.c musl-git/src/math/fabsf.c --- musl-0.9.13/src/math/fabsf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fabsf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,9 @@ -#include "libm.h" +#include +#include float fabsf(float x) { - union fshape u; - - u.value = x; - u.bits &= (uint32_t)-1 / 2; - return u.value; + union {float f; uint32_t i;} u = {x}; + u.i &= 0x7fffffff; + return u.f; } diff -Nur musl-0.9.13/src/math/fabsl.c musl-git/src/math/fabsl.c --- musl-0.9.13/src/math/fabsl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fabsl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,7 +9,7 @@ { union ldshape u = {x}; - u.bits.sign = 0; - return u.value; + u.i.se &= 0x7fff; + return u.f; } #endif diff -Nur musl-0.9.13/src/math/floor.c musl-git/src/math/floor.c --- musl-0.9.13/src/math/floor.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/floor.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,82 +1,24 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_floor.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * floor(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to floor(x). - */ - #include "libm.h" -static const double huge = 1.0e300; - double floor(double x) { - int32_t i0,i1,j0; - uint32_t i,j; + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double_t y; - EXTRACT_WORDS(i0, i1, x); - // FIXME: signed shift - j0 = ((i0>>20)&0x7ff) - 0x3ff; - if (j0 < 20) { - if (j0 < 0) { /* |x| < 1 */ - /* raise inexact if x != 0 */ - if (huge+x > 0.0) { - if (i0 >= 0) { /* x >= 0 */ - i0 = i1 = 0; - } else if (((i0&0x7fffffff)|i1) != 0) { - i0 = 0xbff00000; - i1 = 0; - } - } - } else { - i = 0x000fffff>>j0; - if (((i0&i)|i1) == 0) - return x; /* x is integral */ - /* raise inexact flag */ - if (huge+x > 0.0) { - if (i0 < 0) - i0 += 0x00100000>>j0; - i0 &= ~i; - i1 = 0; - } - } - } else if (j0 > 51) { - if (j0 == 0x400) - return x+x; /* inf or NaN */ - else - return x; /* x is integral */ - } else { - i = (uint32_t)0xffffffff>>(j0-20); - if ((i1&i) == 0) - return x; /* x is integral */ - /* raise inexact flag */ - if (huge+x > 0.0) { - if (i0 < 0) { - if (j0 == 20) - i0++; - else { - j = i1+(1<<(52-j0)); - if (j < i1) - i0++; /* got a carry */ - i1 = j; - } - } - i1 &= ~i; - } + if (e >= 0x3ff+52 || x == 0) + return x; + /* y = int(x) - x, where int(x) is an integer neighbor of x */ + if (u.i >> 63) + y = (double)(x - 0x1p52) + 0x1p52 - x; + else + y = (double)(x + 0x1p52) - 0x1p52 - x; + /* special case because of non-nearest rounding modes */ + if (e <= 0x3ff-1) { + FORCE_EVAL(y); + return u.i >> 63 ? -1 : 0; } - INSERT_WORDS(x, i0, i1); - return x; + if (y > 0) + return x + y - 1; + return x + y; } diff -Nur musl-0.9.13/src/math/floorf.c musl-git/src/math/floorf.c --- musl-0.9.13/src/math/floorf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/floorf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,64 +1,27 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_floorf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * floorf(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to floorf(x). - */ - #include "libm.h" -static const float huge = 1.0e30; - float floorf(float x) { - int32_t i0,j0; - uint32_t i; + union {float f; uint32_t i;} u = {x}; + int e = (int)(u.i >> 23 & 0xff) - 0x7f; + uint32_t m; - GET_FLOAT_WORD(i0, x); - // FIXME: signed shift - j0 = ((i0>>23)&0xff) - 0x7f; - if (j0 < 23) { - if (j0 < 0) { /* |x| < 1 */ - /* raise inexact if x != 0 */ - if (huge+x > 0.0f) { - if (i0 >= 0) /* x >= 0 */ - i0 = 0; - else if ((i0&0x7fffffff) != 0) - i0 = 0xbf800000; - } - } else { - i = 0x007fffff>>j0; - if ((i0&i) == 0) - return x; /* x is integral */ - /* raise inexact flag */ - if (huge+x > 0.0f) { - if (i0 < 0) - i0 += 0x00800000>>j0; - i0 &= ~i; - } - } + if (e >= 23) + return x; + if (e >= 0) { + m = 0x007fffff >> e; + if ((u.i & m) == 0) + return x; + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31) + u.i += m; + u.i &= ~m; } else { - if (j0 == 0x80) /* inf or NaN */ - return x+x; - else - return x; /* x is integral */ + FORCE_EVAL(x + 0x1p120f); + if (u.i >> 31 == 0) + u.i = 0; + else if (u.i << 1) + u.f = -1.0; } - SET_FLOAT_WORD(x, i0); - return x; + return u.f; } diff -Nur musl-0.9.13/src/math/floorl.c musl-git/src/math/floorl.c --- musl-0.9.13/src/math/floorl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/floorl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,23 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_floorl.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * floorl(x) - * Return x rounded toward -inf to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to floorl(x). - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -26,77 +6,31 @@ return floor(x); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#ifdef LDBL_IMPLICIT_NBIT -#define MANH_SIZE (LDBL_MANH_SIZE + 1) -#define INC_MANH(u, c) do { \ - uint64_t o = u.bits.manh; \ - u.bits.manh += (c); \ - if (u.bits.manh < o) \ - u.bits.exp++; \ -} while (0) -#else -#define MANH_SIZE LDBL_MANH_SIZE -#define INC_MANH(u, c) do { \ - uint64_t o = u.bits.manh; \ - u.bits.manh += (c); \ - if (u.bits.manh < o) { \ - u.bits.exp++; \ - u.bits.manh |= 1llu << (LDBL_MANH_SIZE - 1); \ - } \ -} while (0) +#if LDBL_MANT_DIG == 64 +#define TOINT 0x1p63 +#elif LDBL_MANT_DIG == 113 +#define TOINT 0x1p112 #endif - -static const long double huge = 1.0e300; - long double floorl(long double x) { - union IEEEl2bits u = { .e = x }; - int e = u.bits.exp - LDBL_MAX_EXP + 1; - - if (e < MANH_SIZE - 1) { - if (e < 0) { - /* raise inexact if x != 0 */ - if (huge + x > 0.0) - if (u.bits.exp > 0 || - (u.bits.manh | u.bits.manl) != 0) - u.e = u.bits.sign ? -1.0 : 0.0; - } else { - uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); - if (((u.bits.manh & m) | u.bits.manl) == 0) - return x; /* x is integral */ - if (u.bits.sign) { -#ifdef LDBL_IMPLICIT_NBIT - if (e == 0) - u.bits.exp++; - else -#endif - INC_MANH(u, 1llu << (MANH_SIZE - e - 1)); - } - /* raise inexact flag */ - if (huge + x > 0.0) { - u.bits.manh &= ~m; - u.bits.manl = 0; - } - } - } else if (e < LDBL_MANT_DIG - 1) { - uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); - if ((u.bits.manl & m) == 0) - return x; /* x is integral */ - if (u.bits.sign) { - if (e == MANH_SIZE - 1) - INC_MANH(u, 1); - else { - uint64_t o = u.bits.manl; - u.bits.manl += 1llu << (LDBL_MANT_DIG - e - 1); - if (u.bits.manl < o) /* got a carry */ - INC_MANH(u, 1); - } - } - /* raise inexact flag */ - if (huge + x > 0.0) - u.bits.manl &= ~m; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + long double y; + + if (e >= 0x3fff+LDBL_MANT_DIG-1 || x == 0) + return x; + /* y = int(x) - x, where int(x) is an integer neighbor of x */ + if (u.i.se >> 15) + y = x - TOINT + TOINT - x; + else + y = x + TOINT - TOINT - x; + /* special case because of non-nearest rounding modes */ + if (e <= 0x3fff-1) { + FORCE_EVAL(y); + return u.i.se >> 15 ? -1 : 0; } - return u.e; + if (y > 0) + return x + y - 1; + return x + y; } #endif diff -Nur musl-0.9.13/src/math/fma.c musl-git/src/math/fma.c --- musl-0.9.13/src/math/fma.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fma.c 2013-09-16 20:31:39.000000000 +0200 @@ -2,16 +2,6 @@ #include "libm.h" #if LDBL_MANT_DIG==64 && LDBL_MAX_EXP==16384 -union ld80 { - long double x; - struct { - uint64_t m; - uint16_t e : 15; - uint16_t s : 1; - uint16_t pad; - } bits; -}; - /* exact add, assumes exponent_x >= exponent_y */ static void add(long double *hi, long double *lo, long double x, long double y) { @@ -45,25 +35,25 @@ */ static long double adjust(long double hi, long double lo) { - union ld80 uhi, ulo; + union ldshape uhi, ulo; if (lo == 0) return hi; - uhi.x = hi; - if (uhi.bits.m & 0x3ff) + uhi.f = hi; + if (uhi.i.m & 0x3ff) return hi; - ulo.x = lo; - if (uhi.bits.s == ulo.bits.s) - uhi.bits.m++; + ulo.f = lo; + if ((uhi.i.se & 0x8000) == (ulo.i.se & 0x8000)) + uhi.i.m++; else { - uhi.bits.m--; /* handle underflow and take care of ld80 implicit msb */ - if (uhi.bits.m == (uint64_t)-1/2) { - uhi.bits.m *= 2; - uhi.bits.e--; + if (uhi.i.m << 1 == 0) { + uhi.i.m = 0; + uhi.i.se--; } + uhi.i.m--; } - return uhi.x; + return uhi.f; } /* adjusted add so the result is correct when rounded to double (or less) precision */ @@ -82,9 +72,9 @@ static int getexp(long double x) { - union ld80 u; - u.x = x; - return u.bits.e; + union ldshape u; + u.f = x; + return u.i.se & 0x7fff; } double fma(double x, double y, double z) @@ -242,16 +232,16 @@ static inline double add_adjusted(double a, double b) { struct dd sum; - uint64_t hibits, lobits; + union {double f; uint64_t i;} uhi, ulo; sum = dd_add(a, b); if (sum.lo != 0) { - EXTRACT_WORD64(hibits, sum.hi); - if ((hibits & 1) == 0) { + uhi.f = sum.hi; + if ((uhi.i & 1) == 0) { /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */ - EXTRACT_WORD64(lobits, sum.lo); - hibits += 1 - ((hibits ^ lobits) >> 62); - INSERT_WORD64(sum.hi, hibits); + ulo.f = sum.lo; + uhi.i += 1 - ((uhi.i ^ ulo.i) >> 62); + sum.hi = uhi.f; } } return (sum.hi); @@ -265,7 +255,7 @@ static inline double add_and_denormalize(double a, double b, int scale) { struct dd sum; - uint64_t hibits, lobits; + union {double f; uint64_t i;} uhi, ulo; int bits_lost; sum = dd_add(a, b); @@ -281,13 +271,13 @@ * break the ties manually. */ if (sum.lo != 0) { - EXTRACT_WORD64(hibits, sum.hi); - bits_lost = -((int)(hibits >> 52) & 0x7ff) - scale + 1; - if (bits_lost != 1 ^ (int)(hibits & 1)) { + uhi.f = sum.hi; + bits_lost = -((int)(uhi.i >> 52) & 0x7ff) - scale + 1; + if (bits_lost != 1 ^ (int)(uhi.i & 1)) { /* hibits += (int)copysign(1.0, sum.hi * sum.lo) */ - EXTRACT_WORD64(lobits, sum.lo); - hibits += 1 - (((hibits ^ lobits) >> 62) & 2); - INSERT_WORD64(sum.hi, hibits); + ulo.f = sum.lo; + uhi.i += 1 - (((uhi.i ^ ulo.i) >> 62) & 2); + sum.hi = uhi.f; } } return scalbn(sum.hi, scale); diff -Nur musl-0.9.13/src/math/fmal.c musl-git/src/math/fmal.c --- musl-0.9.13/src/math/fmal.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fmal.c 2013-09-16 20:31:39.000000000 +0200 @@ -34,6 +34,13 @@ } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 #include +#if LDBL_MANT_DIG == 64 +#define LASTBIT(u) (u.i.m & 1) +#define SPLIT (0x1p32L + 1) +#elif LDBL_MANT_DIG == 113 +#define LASTBIT(u) (u.i.lo & 1) +#define SPLIT (0x1p57L + 1) +#endif /* * A struct dd represents a floating-point number with twice the precision @@ -75,12 +82,12 @@ static inline long double add_adjusted(long double a, long double b) { struct dd sum; - union IEEEl2bits u; + union ldshape u; sum = dd_add(a, b); if (sum.lo != 0) { - u.e = sum.hi; - if ((u.bits.manl & 1) == 0) + u.f = sum.hi; + if (!LASTBIT(u)) sum.hi = nextafterl(sum.hi, INFINITY * sum.lo); } return (sum.hi); @@ -95,7 +102,7 @@ { struct dd sum; int bits_lost; - union IEEEl2bits u; + union ldshape u; sum = dd_add(a, b); @@ -110,9 +117,9 @@ * break the ties manually. */ if (sum.lo != 0) { - u.e = sum.hi; - bits_lost = -u.bits.exp - scale + 1; - if (bits_lost != 1 ^ (int)(u.bits.manl & 1)) + u.f = sum.hi; + bits_lost = -u.i.se - scale + 1; + if ((bits_lost != 1) ^ LASTBIT(u)) sum.hi = nextafterl(sum.hi, INFINITY * sum.lo); } return scalbnl(sum.hi, scale); @@ -125,20 +132,15 @@ */ static inline struct dd dd_mul(long double a, long double b) { -#if LDBL_MANT_DIG == 64 - static const long double split = 0x1p32L + 1.0; -#elif LDBL_MANT_DIG == 113 - static const long double split = 0x1p57L + 1.0; -#endif struct dd ret; long double ha, hb, la, lb, p, q; - p = a * split; + p = a * SPLIT; ha = a - p; ha += p; la = a - ha; - p = b * split; + p = b * SPLIT; hb = b - p; hb += p; lb = b - hb; diff -Nur musl-0.9.13/src/math/fmod.c musl-git/src/math/fmod.c --- musl-0.9.13/src/math/fmod.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fmod.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,145 +1,68 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_fmod.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * fmod(x,y) - * Return x mod y in exact arithmetic - * Method: shift and subtract - */ - -#include "libm.h" - -static const double Zero[] = {0.0, -0.0,}; +#include +#include double fmod(double x, double y) { - int32_t n,hx,hy,hz,ix,iy,sx,i; - uint32_t lx,ly,lz; + union {double f; uint64_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>52 & 0x7ff; + int ey = uy.i>>52 & 0x7ff; + int sx = ux.i>>63; + uint64_t i; + + /* in the followings uxi should be ux.i, but then gcc wrongly adds */ + /* float load/store to inner loops ruining performance and code size */ + uint64_t uxi = ux.i; - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - sx = hx & 0x80000000; /* sign of x */ - hx ^= sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ - - /* purge off exception values */ - if ((hy|ly) == 0 || hx >= 0x7ff00000 || /* y=0,or x not finite */ - (hy|((ly|-ly)>>31)) > 0x7ff00000) /* or y is NaN */ + if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) return (x*y)/(x*y); - if (hx <= hy) { - if (hx < hy || lx < ly) /* |x| < |y| */ - return x; - if (lx == ly) /* |x| = |y|, return x*0 */ - return Zero[(uint32_t)sx>>31]; - } - - /* determine ix = ilogb(x) */ - if (hx < 0x00100000) { /* subnormal x */ - if (hx == 0) { - for (ix = -1043, i = lx; i > 0; i <<= 1) - ix -= 1; - } else { - for (ix = -1022, i = hx<<11; i > 0; i <<= 1) - ix -= 1; - } - } else - ix = (hx>>20) - 1023; - - /* determine iy = ilogb(y) */ - if (hy < 0x00100000) { /* subnormal y */ - if (hy == 0) { - for (iy = -1043, i = ly; i > 0; i <<= 1) - iy -= 1; - } else { - for (iy = -1022, i = hy<<11; i > 0; i <<= 1) - iy -= 1; - } - } else - iy = (hy>>20) - 1023; - - /* set up {hx,lx}, {hy,ly} and align y to x */ - if (ix >= -1022) - hx = 0x00100000|(0x000fffff&hx); - else { /* subnormal x, shift x to normal */ - n = -1022-ix; - if (n <= 31) { - hx = (hx<>(32-n)); - lx <<= n; - } else { - hx = lx<<(n-32); - lx = 0; - } - } - if(iy >= -1022) - hy = 0x00100000|(0x000fffff&hy); - else { /* subnormal y, shift y to normal */ - n = -1022-iy; - if (n <= 31) { - hy = (hy<>(32-n)); - ly <<= n; - } else { - hy = ly<<(n-32); - ly = 0; - } - } - - /* fix point fmod */ - n = ix - iy; - while (n--) { - hz = hx-hy; - lz = lx-ly; - if (lx < ly) - hz -= 1; - if (hz < 0) { - hx = hx+hx+(lx>>31); - lx = lx+lx; - } else { - if ((hz|lz) == 0) /* return sign(x)*0 */ - return Zero[(uint32_t)sx>>31]; - hx = hz+hz+(lz>>31); - lx = lz+lz; - } - } - hz = hx-hy; - lz = lx-ly; - if (lx < ly) - hz -= 1; - if (hz >= 0) { - hx = hz; - lx = lz; - } - - /* convert back to floating value and restore the sign */ - if ((hx|lx) == 0) /* return sign(x)*0 */ - return Zero[(uint32_t)sx>>31]; - while (hx < 0x00100000) { /* normalize x */ - hx = hx+hx+(lx>>31); - lx = lx+lx; - iy -= 1; - } - if (iy >= -1022) { /* normalize output */ - hx = ((hx-0x00100000)|((iy+1023)<<20)); - INSERT_WORDS(x, hx|sx, lx); - } else { /* subnormal output */ - n = -1022 - iy; - if (n <= 20) { - lx = (lx>>n)|((uint32_t)hx<<(32-n)); - hx >>= n; - } else if (n <= 31) { - lx = (hx<<(32-n))|(lx>>n); - hx = sx; - } else { - lx = hx>>(n-32); hx = sx; - } - INSERT_WORDS(x, hx|sx, lx); - } - return x; /* exact output */ + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; + return x; + } + + /* normalize x and y */ + if (!ex) { + for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1ULL >> 12; + uxi |= 1ULL << 52; + } + if (!ey) { + for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1ULL >> 12; + uy.i |= 1ULL << 52; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 63 == 0) { + if (i == 0) + return 0*x; + uxi = i; + } + for (; uxi>>52 == 0; uxi <<= 1, ex--); + + /* scale result */ + if (ex > 0) { + uxi -= 1ULL << 52; + uxi |= (uint64_t)ex << 52; + } else { + uxi >>= -ex + 1; + } + uxi |= (uint64_t)sx << 63; + ux.i = uxi; + return ux.f; } diff -Nur musl-0.9.13/src/math/fmodf.c musl-git/src/math/fmodf.c --- musl-0.9.13/src/math/fmodf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fmodf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,104 +1,65 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_fmodf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * fmodf(x,y) - * Return x mod y in exact arithmetic - * Method: shift and subtract - */ - -#include "libm.h" - -static const float Zero[] = {0.0, -0.0,}; +#include +#include float fmodf(float x, float y) { - int32_t n,hx,hy,hz,ix,iy,sx,i; + union {float f; uint32_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>23 & 0xff; + int ey = uy.i>>23 & 0xff; + uint32_t sx = ux.i & 0x80000000; + uint32_t i; + uint32_t uxi = ux.i; - GET_FLOAT_WORD(hx, x); - GET_FLOAT_WORD(hy, y); - sx = hx & 0x80000000; /* sign of x */ - hx ^= sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ - - /* purge off exception values */ - if (hy == 0 || hx >= 0x7f800000 || /* y=0,or x not finite */ - hy > 0x7f800000) /* or y is NaN */ + if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) return (x*y)/(x*y); - if (hx < hy) /* |x| < |y| */ + if (uxi<<1 <= uy.i<<1) { + if (uxi<<1 == uy.i<<1) + return 0*x; return x; - if (hx == hy) /* |x| = |y|, return x*0 */ - return Zero[(uint32_t)sx>>31]; - - /* determine ix = ilogb(x) */ - if (hx < 0x00800000) { /* subnormal x */ - for (ix = -126, i = hx<<8; i > 0; i <<= 1) - ix -= 1; - } else - ix = (hx>>23) - 127; - - /* determine iy = ilogb(y) */ - if (hy < 0x00800000) { /* subnormal y */ - for (iy = -126, i = hy<<8; i >= 0; i <<= 1) - iy -= 1; - } else - iy = (hy>>23) - 127; + } - /* set up {hx,lx}, {hy,ly} and align y to x */ - if (ix >= -126) - hx = 0x00800000|(0x007fffff&hx); - else { /* subnormal x, shift x to normal */ - n = -126-ix; - hx = hx<= -126) - hy = 0x00800000|(0x007fffff&hy); - else { /* subnormal y, shift y to normal */ - n = -126-iy; - hy = hy<>31 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1U >> 9; + uxi |= 1U << 23; + } + if (!ey) { + for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1U >> 9; + uy.i |= 1U << 23; } - /* fix point fmod */ - n = ix - iy; - while (n--) { - hz = hx-hy; - if (hz<0) - hx = hx+hx; - else { - if(hz == 0) /* return sign(x)*0 */ - return Zero[(uint32_t)sx>>31]; - hx = hz+hz; + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; } + uxi <<= 1; + } + i = uxi - uy.i; + if (i >> 31 == 0) { + if (i == 0) + return 0*x; + uxi = i; } - hz = hx-hy; - if (hz >= 0) - hx = hz; + for (; uxi>>23 == 0; uxi <<= 1, ex--); - /* convert back to floating value and restore the sign */ - if (hx == 0) /* return sign(x)*0 */ - return Zero[(uint32_t)sx>>31]; - while (hx < 0x00800000) { /* normalize x */ - hx = hx+hx; - iy -= 1; - } - if (iy >= -126) { /* normalize output */ - hx = ((hx-0x00800000)|((iy+127)<<23)); - SET_FLOAT_WORD(x, hx|sx); - } else { /* subnormal output */ - n = -126 - iy; - hx >>= n; - SET_FLOAT_WORD(x, hx|sx); + /* scale result up */ + if (ex > 0) { + uxi -= 1U << 23; + uxi |= (uint32_t)ex << 23; + } else { + uxi >>= -ex + 1; } - return x; /* exact output */ + uxi |= sx; + ux.i = uxi; + return ux.f; } diff -Nur musl-0.9.13/src/math/fmodl.c musl-git/src/math/fmodl.c --- musl-0.9.13/src/math/fmodl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/fmodl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,15 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_fmodl.c */ -/*- - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -18,141 +6,100 @@ return fmod(x, y); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#define BIAS (LDBL_MAX_EXP - 1) - -#if LDBL_MANL_SIZE > 32 -typedef uint64_t manl_t; -#else -typedef uint32_t manl_t; -#endif - -#if LDBL_MANH_SIZE > 32 -typedef uint64_t manh_t; -#else -typedef uint32_t manh_t; -#endif - -/* - * These macros add and remove an explicit integer bit in front of the - * fractional mantissa, if the architecture doesn't have such a bit by - * default already. - */ -#ifdef LDBL_IMPLICIT_NBIT -#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE)) -#define HFRAC_BITS LDBL_MANH_SIZE -#else -#define SET_NBIT(hx) (hx) -#define HFRAC_BITS (LDBL_MANH_SIZE - 1) -#endif - -#define MANL_SHIFT (LDBL_MANL_SIZE - 1) - -static const long double Zero[] = {0.0, -0.0,}; - -/* - * fmodl(x,y) - * Return x mod y in exact arithmetic - * Method: shift and subtract - * - * Assumptions: - * - The low part of the mantissa fits in a manl_t exactly. - * - The high part of the mantissa fits in an int64_t with enough room - * for an explicit integer bit in front of the fractional bits. - */ long double fmodl(long double x, long double y) { - union IEEEl2bits ux, uy; - int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */ - manh_t hy; - manl_t lx,ly,lz; - int ix,iy,n,sx; - - ux.e = x; - uy.e = y; - sx = ux.bits.sign; + union ldshape ux = {x}, uy = {y}; + int ex = ux.i.se & 0x7fff; + int ey = uy.i.se & 0x7fff; + int sx = ux.i.se & 0x8000; - /* purge off exception values */ - if ((uy.bits.exp|uy.bits.manh|uy.bits.manl) == 0 || /* y=0 */ - ux.bits.exp == BIAS + LDBL_MAX_EXP || /* or x not finite */ - (uy.bits.exp == BIAS + LDBL_MAX_EXP && - ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl) != 0)) /* or y is NaN */ + if (y == 0 || isnan(y) || ex == 0x7fff) return (x*y)/(x*y); - if (ux.bits.exp <= uy.bits.exp) { - if (ux.bits.exp < uy.bits.exp || - (ux.bits.manh<=uy.bits.manh && - (ux.bits.manh>MANL_SHIFT); - lx = lx+lx; + ux.i.se = ex; + uy.i.se = ey; + if (ux.f <= uy.f) { + if (ux.f == uy.f) + return 0*x; + return x; + } + + /* normalize x and y */ + if (!ex) { + ux.f *= 0x1p120f; + ex = ux.i.se - 120; + } + if (!ey) { + uy.f *= 0x1p120f; + ey = uy.i.se - 120; + } + + /* x mod y */ +#if LDBL_MANT_DIG == 64 + uint64_t i, mx, my; + mx = ux.i.m; + my = uy.i.m; + for (; ex > ey; ex--) { + i = mx - my; + if (mx >= my) { + if (i == 0) + return 0*x; + mx = 2*i; + } else if (2*mx < mx) { + mx = 2*mx - my; } else { - if ((hz|lz)==0) /* return sign(x)*0 */ - return Zero[sx]; - hx = hz+hz+(lz>>MANL_SHIFT); - lx = lz+lz; + mx = 2*mx; } } - hz = hx-hy; - lz = lx-ly; - if (lx < ly) - hz -= 1; - if (hz >= 0) { - hx = hz; - lx = lz; + i = mx - my; + if (mx >= my) { + if (i == 0) + return 0*x; + mx = i; + } + for (; mx >> 63 == 0; mx *= 2, ex--); + ux.i.m = mx; +#elif LDBL_MANT_DIG == 113 + uint64_t hi, lo, xhi, xlo, yhi, ylo; + xhi = (ux.i2.hi & -1ULL>>16) | 1ULL<<48; + yhi = (uy.i2.hi & -1ULL>>16) | 1ULL<<48; + xlo = ux.i2.lo; + ylo = ux.i2.lo; + for (; ex > ey; ex--) { + hi = xhi - yhi; + lo = xlo - ylo; + if (xlo < ylo) + hi -= 1; + if (hi >> 63 == 0) { + if ((hi|lo) == 0) + return 0*x; + xhi = 2*hi + (lo>>63); + xlo = 2*lo; + } else { + xhi = 2*xhi + (xlo>>63); + xlo = 2*xlo; + } } + hi = xhi - yhi; + lo = xlo - ylo; + if (xlo < ylo) + hi -= 1; + if (hi >> 63 == 0) { + if ((hi|lo) == 0) + return 0*x; + xhi = hi; + xlo = lo; + } + for (; xhi >> 48 == 0; xhi = 2*xhi + (xlo>>63), xlo = 2*xlo, ex--); + ux.i2.hi = xhi; + ux.i2.lo = xlo; +#endif - /* convert back to floating value and restore the sign */ - if ((hx|lx) == 0) /* return sign(x)*0 */ - return Zero[sx]; - while (hx < (1ULL<>MANL_SHIFT); - lx = lx+lx; - iy -= 1; - } - ux.bits.manh = hx; /* The mantissa is truncated here if needed. */ - ux.bits.manl = lx; - if (iy < LDBL_MIN_EXP) { - ux.bits.exp = iy + (BIAS + 512); - ux.e *= 0x1p-512; - } else { - ux.bits.exp = iy + BIAS; - } - return ux.e; /* exact output */ + /* scale result */ + if (ex <= 0) { + ux.i.se = (ex+120)|sx; + ux.f *= 0x1p-120f; + } else + ux.i.se = ex|sx; + return ux.f; } #endif diff -Nur musl-0.9.13/src/math/frexpl.c musl-git/src/math/frexpl.c --- musl-0.9.13/src/math/frexpl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/frexpl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,20 +1,20 @@ -#include -#include -#include - -#if LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 - -/* This version is for 80-bit little endian long double */ +#include "libm.h" +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 long double frexpl(long double x, int *e) { - union { long double ld; uint16_t hw[5]; } y = { x }; - int ee = y.hw[4]&0x7fff; + return frexp(x, e); +} +#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +long double frexpl(long double x, int *e) +{ + union ldshape u = {x}; + int ee = u.i.se & 0x7fff; if (!ee) { if (x) { - x = frexpl(x*0x1p64, e); - *e -= 64; + x = frexpl(x*0x1p120, e); + *e -= 120; } else *e = 0; return x; } else if (ee == 0x7fff) { @@ -22,16 +22,8 @@ } *e = ee - 0x3ffe; - y.hw[4] &= 0x8000; - y.hw[4] |= 0x3ffe; - return y.ld; + u.i.se &= 0x8000; + u.i.se |= 0x3ffe; + return u.f; } - -#else - -long double frexpl(long double x, int *e) -{ - return frexp(x, e); -} - #endif diff -Nur musl-0.9.13/src/math/hypot.c musl-git/src/math/hypot.c --- musl-0.9.13/src/math/hypot.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/hypot.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,123 +1,67 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_hypot.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* hypot(x,y) - * - * Method : - * If (assume round-to-nearest) z=x*x+y*y - * has error less than sqrt(2)/2 ulp, then - * sqrt(z) has error less than 1 ulp (exercise). - * - * So, compute sqrt(x*x+y*y) with some care as - * follows to get the error below 1 ulp: - * - * Assume x>y>0; - * (if possible, set rounding to round-to-nearest) - * 1. if x > 2y use - * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y - * where x1 = x with lower 32 bits cleared, x2 = x-x1; else - * 2. if x <= 2y use - * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) - * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, - * y1= y with lower 32 bits chopped, y2 = y-y1. - * - * NOTE: scaling may be necessary if some argument is too - * large or too tiny - * - * Special cases: - * hypot(x,y) is INF if x or y is +INF or -INF; else - * hypot(x,y) is NAN if x or y is NAN. - * - * Accuracy: - * hypot(x,y) returns sqrt(x^2+y^2) with error less - * than 1 ulps (units in the last place) - */ +#include +#include +#include -#include "libm.h" +#if FLT_EVAL_METHOD > 1U && LDBL_MANT_DIG == 64 +#define SPLIT (0x1p32 + 1) +#else +#define SPLIT (0x1p27 + 1) +#endif + +static void sq(double_t *hi, double_t *lo, double x) +{ + double_t xh, xl, xc; + + xc = x*SPLIT; + xh = x - xc + xc; + xl = x - xh; + *hi = x*x; + *lo = xh*xh - *hi + 2*xh*xl + xl*xl; +} double hypot(double x, double y) { - double a,b,t1,t2,y1,y2,w; - int32_t j,k,ha,hb; + union {double f; uint64_t i;} ux = {x}, uy = {y}, ut; + int ex, ey; + double_t hx, lx, hy, ly, z; - GET_HIGH_WORD(ha, x); - ha &= 0x7fffffff; - GET_HIGH_WORD(hb, y); - hb &= 0x7fffffff; - if (hb > ha) { - a = y; - b = x; - j=ha; ha=hb; hb=j; - } else { - a = x; - b = y; + /* arrange |x| >= |y| */ + ux.i &= -1ULL>>1; + uy.i &= -1ULL>>1; + if (ux.i < uy.i) { + ut = ux; + ux = uy; + uy = ut; } - a = fabs(a); - b = fabs(b); - if (ha - hb > 0x3c00000) /* x/y > 2**60 */ - return a+b; - k = 0; - if (ha > 0x5f300000) { /* a > 2**500 */ - if(ha >= 0x7ff00000) { /* Inf or NaN */ - uint32_t low; - /* Use original arg order iff result is NaN; quieten sNaNs. */ - w = fabs(x+0.0) - fabs(y+0.0); - GET_LOW_WORD(low, a); - if (((ha&0xfffff)|low) == 0) w = a; - GET_LOW_WORD(low, b); - if (((hb^0x7ff00000)|low) == 0) w = b; - return w; - } - /* scale a and b by 2**-600 */ - ha -= 0x25800000; hb -= 0x25800000; k += 600; - SET_HIGH_WORD(a, ha); - SET_HIGH_WORD(b, hb); - } - if (hb < 0x20b00000) { /* b < 2**-500 */ - if (hb <= 0x000fffff) { /* subnormal b or 0 */ - uint32_t low; - GET_LOW_WORD(low, b); - if ((hb|low) == 0) - return a; - t1 = 0; - SET_HIGH_WORD(t1, 0x7fd00000); /* t1 = 2^1022 */ - b *= t1; - a *= t1; - k -= 1022; - } else { /* scale a and b by 2^600 */ - ha += 0x25800000; /* a *= 2^600 */ - hb += 0x25800000; /* b *= 2^600 */ - k -= 600; - SET_HIGH_WORD(a, ha); - SET_HIGH_WORD(b, hb); - } - } - /* medium size a and b */ - w = a - b; - if (w > b) { - t1 = 0; - SET_HIGH_WORD(t1, ha); - t2 = a-t1; - w = sqrt(t1*t1-(b*(-b)-t2*(a+t1))); - } else { - a = a + a; - y1 = 0; - SET_HIGH_WORD(y1, hb); - y2 = b - y1; - t1 = 0; - SET_HIGH_WORD(t1, ha+0x00100000); - t2 = a - t1; - w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); + + /* special cases */ + ex = ux.i>>52; + ey = uy.i>>52; + x = ux.f; + y = uy.f; + /* note: hypot(inf,nan) == inf */ + if (ey == 0x7ff) + return y; + if (ex == 0x7ff || uy.i == 0) + return x; + /* note: hypot(x,y) ~= x + y*y/x/2 with inexact for small y/x */ + /* 64 difference is enough for ld80 double_t */ + if (ex - ey > 64) + return x + y; + + /* precise sqrt argument in nearest rounding mode without overflow */ + /* xh*xh must not overflow and xl*xl must not underflow in sq */ + z = 1; + if (ex > 0x3ff+510) { + z = 0x1p700; + x *= 0x1p-700; + y *= 0x1p-700; + } else if (ey < 0x3ff-450) { + z = 0x1p-700; + x *= 0x1p700; + y *= 0x1p700; } - if (k) - w = scalbn(w, k); - return w; + sq(&hx, &lx, x); + sq(&hy, &ly, y); + return z*sqrt(ly+lx+hy+hx); } diff -Nur musl-0.9.13/src/math/hypotf.c musl-git/src/math/hypotf.c --- musl-0.9.13/src/math/hypotf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/hypotf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,86 +1,35 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_hypotf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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 "libm.h" +#include +#include float hypotf(float x, float y) { - float a,b,t1,t2,y1,y2,w; - int32_t j,k,ha,hb; + union {float f; uint32_t i;} ux = {x}, uy = {y}, ut; + float_t z; - GET_FLOAT_WORD(ha,x); - ha &= 0x7fffffff; - GET_FLOAT_WORD(hb,y); - hb &= 0x7fffffff; - if (hb > ha) { - a = y; - b = x; - j=ha; ha=hb; hb=j; - } else { - a = x; - b = y; - } - a = fabsf(a); - b = fabsf(b); - if (ha - hb > 0xf000000) /* x/y > 2**30 */ - return a+b; - k = 0; - if (ha > 0x58800000) { /* a > 2**50 */ - if(ha >= 0x7f800000) { /* Inf or NaN */ - /* Use original arg order iff result is NaN; quieten sNaNs. */ - w = fabsf(x+0.0f) - fabsf(y+0.0f); - if (ha == 0x7f800000) w = a; - if (hb == 0x7f800000) w = b; - return w; - } - /* scale a and b by 2**-68 */ - ha -= 0x22000000; hb -= 0x22000000; k += 68; - SET_FLOAT_WORD(a, ha); - SET_FLOAT_WORD(b, hb); - } - if (hb < 0x26800000) { /* b < 2**-50 */ - if (hb <= 0x007fffff) { /* subnormal b or 0 */ - if (hb == 0) - return a; - SET_FLOAT_WORD(t1, 0x7e800000); /* t1 = 2^126 */ - b *= t1; - a *= t1; - k -= 126; - } else { /* scale a and b by 2^68 */ - ha += 0x22000000; /* a *= 2^68 */ - hb += 0x22000000; /* b *= 2^68 */ - k -= 68; - SET_FLOAT_WORD(a, ha); - SET_FLOAT_WORD(b, hb); - } + ux.i &= -1U>>1; + uy.i &= -1U>>1; + if (ux.i < uy.i) { + ut = ux; + ux = uy; + uy = ut; } - /* medium size a and b */ - w = a - b; - if (w > b) { - SET_FLOAT_WORD(t1, ha&0xfffff000); - t2 = a - t1; - w = sqrtf(t1*t1-(b*(-b)-t2*(a+t1))); - } else { - a = a + a; - SET_FLOAT_WORD(y1, hb&0xfffff000); - y2 = b - y1; - SET_FLOAT_WORD(t1,(ha+0x00800000)&0xfffff000); - t2 = a - t1; - w = sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b))); + + x = ux.f; + y = uy.f; + if (uy.i == 0xff<<23) + return y; + if (ux.i >= 0xff<<23 || uy.i == 0 || ux.i - uy.i >= 25<<23) + return x + y; + + z = 1; + if (ux.i >= (0x7f+60)<<23) { + z = 0x1p90f; + x *= 0x1p-90f; + y *= 0x1p-90f; + } else if (uy.i < (0x7f-60)<<23) { + z = 0x1p-90f; + x *= 0x1p90f; + y *= 0x1p90f; } - if (k) - w = scalbnf(w, k); - return w; + return z*sqrtf((double)x*x + (double)y*y); } diff -Nur musl-0.9.13/src/math/hypotl.c musl-git/src/math/hypotl.c --- musl-0.9.13/src/math/hypotl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/hypotl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,16 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_hypotl.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* long double version of hypot(). See comments in hypot.c. */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -19,130 +6,61 @@ return hypot(x, y); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#define GET_LDBL_EXPSIGN(i, v) do { \ - union IEEEl2bits uv; \ - \ - uv.e = v; \ - i = uv.xbits.expsign; \ -} while (0) - -#define GET_LDBL_MAN(h, l, v) do { \ - union IEEEl2bits uv; \ - \ - uv.e = v; \ - h = uv.bits.manh; \ - l = uv.bits.manl; \ -} while (0) - -#define SET_LDBL_EXPSIGN(v, i) do { \ - union IEEEl2bits uv; \ - \ - uv.e = v; \ - uv.xbits.expsign = i; \ - v = uv.e; \ -} while (0) - -#undef GET_HIGH_WORD -#define GET_HIGH_WORD(i, v) GET_LDBL_EXPSIGN(i, v) -#undef SET_HIGH_WORD -#define SET_HIGH_WORD(v, i) SET_LDBL_EXPSIGN(v, i) - -#define DESW(exp) (exp) /* delta expsign word */ -#define ESW(exp) (MAX_EXP - 1 + (exp)) /* expsign word */ -#define MANT_DIG LDBL_MANT_DIG -#define MAX_EXP LDBL_MAX_EXP - -#if LDBL_MANL_SIZE > 32 -typedef uint64_t man_t; -#else -typedef uint32_t man_t; +#if LDBL_MANT_DIG == 64 +#define SPLIT (0x1p32L+1) +#elif LDBL_MANT_DIG == 113 +#define SPLIT (0x1p57L+1) #endif -long double hypotl(long double x, long double y) +static void sq(long double *hi, long double *lo, long double x) { - long double a=x,b=y,t1,t2,y1,y2,w; - int32_t j,k,ha,hb; + long double xh, xl, xc; + xc = x*SPLIT; + xh = x - xc + xc; + xl = x - xh; + *hi = x*x; + *lo = xh*xh - *hi + 2*xh*xl + xl*xl; +} - GET_HIGH_WORD(ha, x); - ha &= 0x7fff; - GET_HIGH_WORD(hb, y); - hb &= 0x7fff; - if (hb > ha) { - a = y; - b = x; - j=ha; ha=hb; hb=j; - } else { - a = x; - b = y; - } - a = fabsl(a); - b = fabsl(b); - if (ha - hb > DESW(MANT_DIG+7)) /* x/y > 2**(MANT_DIG+7) */ - return a+b; - k = 0; - if (ha > ESW(MAX_EXP/2-12)) { /* a>2**(MAX_EXP/2-12) */ - if (ha >= ESW(MAX_EXP)) { /* Inf or NaN */ - man_t manh, manl; - /* Use original arg order iff result is NaN; quieten sNaNs. */ - w = fabsl(x+0.0)-fabsl(y+0.0); - GET_LDBL_MAN(manh,manl,a); - if (manh == LDBL_NBIT && manl == 0) w = a; - GET_LDBL_MAN(manh,manl,b); - if (hb >= ESW(MAX_EXP) && manh == LDBL_NBIT && manl == 0) w = b; - return w; - } - /* scale a and b by 2**-(MAX_EXP/2+88) */ - ha -= DESW(MAX_EXP/2+88); hb -= DESW(MAX_EXP/2+88); - k += MAX_EXP/2+88; - SET_HIGH_WORD(a, ha); - SET_HIGH_WORD(b, hb); - } - if (hb < ESW(-(MAX_EXP/2-12))) { /* b < 2**-(MAX_EXP/2-12) */ - if (hb <= 0) { /* subnormal b or 0 */ - man_t manh, manl; - GET_LDBL_MAN(manh,manl,b); - if ((manh|manl) == 0) - return a; - t1 = 0; - SET_HIGH_WORD(t1, ESW(MAX_EXP-2)); /* t1 = 2^(MAX_EXP-2) */ - b *= t1; - a *= t1; - k -= MAX_EXP-2; - } else { /* scale a and b by 2^(MAX_EXP/2+88) */ - ha += DESW(MAX_EXP/2+88); - hb += DESW(MAX_EXP/2+88); - k -= MAX_EXP/2+88; - SET_HIGH_WORD(a, ha); - SET_HIGH_WORD(b, hb); - } - } - /* medium size a and b */ - w = a - b; - if (w > b) { - t1 = a; - union IEEEl2bits uv; - uv.e = t1; uv.bits.manl = 0; t1 = uv.e; - t2 = a-t1; - w = sqrtl(t1*t1-(b*(-b)-t2*(a+t1))); +long double hypotl(long double x, long double y) +{ + union ldshape ux = {x}, uy = {y}; + int ex, ey; + long double hx, lx, hy, ly, z; + + ux.i.se &= 0x7fff; + uy.i.se &= 0x7fff; + if (ux.i.se < uy.i.se) { + ex = uy.i.se; + ey = ux.i.se; + x = uy.f; + y = ux.f; } else { - a = a+a; - y1 = b; - union IEEEl2bits uv; - uv.e = y1; uv.bits.manl = 0; y1 = uv.e; - y2 = b - y1; - t1 = a; - uv.e = t1; uv.bits.manl = 0; t1 = uv.e; - t2 = a - t1; - w = sqrtl(t1*y1-(w*(-w)-(t1*y2+t2*b))); + ex = ux.i.se; + ey = uy.i.se; + x = ux.f; + y = uy.f; } - if(k!=0) { - uint32_t high; - t1 = 1.0; - GET_HIGH_WORD(high, t1); - SET_HIGH_WORD(t1, high+DESW(k)); - return t1*w; + + if (ex == 0x7fff && isinf(y)) + return y; + if (ex == 0x7fff || y == 0) + return x; + if (ex - ey > LDBL_MANT_DIG) + return x + y; + + z = 1; + if (ex > 0x3fff+8000) { + z = 0x1p10000L; + x *= 0x1p-10000L; + y *= 0x1p-10000L; + } else if (ey < 0x3fff-8000) { + z = 0x1p-10000L; + x *= 0x1p10000L; + y *= 0x1p10000L; } - return w; + sq(&hx, &lx, x); + sq(&hy, &ly, y); + return z*sqrtl(ly+lx+hy+hx); } #endif diff -Nur musl-0.9.13/src/math/i386/exp.s musl-git/src/math/i386/exp.s --- musl-0.9.13/src/math/i386/exp.s 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/i386/exp.s 2013-09-16 20:31:39.000000000 +0200 @@ -95,42 +95,32 @@ .type exp2,@function exp2: fldl 4(%esp) -1: pushl $0x467ff000 - flds (%esp) # 16380 - xorl %eax,%eax - pushl $0x80000000 - push %eax - fld %st(1) - fabs - fucomp %st(1) - fnstsw - fstp %st(0) - sahf - ja 3f # |x| > 16380 - jp 2f # x is nan (avoid invalid except in fistp) +1: sub $12,%esp fld %st(0) - fistpl 8(%esp) - fildl 8(%esp) - fxch %st(1) - fsub %st(1) - mov $0x3fff,%eax - add %eax,8(%esp) - f2xm1 - fld1 - faddp # 2^(x-rint(x)) - fldt (%esp) # 2^rint(x) - fmulp - fstp %st(1) -2: add $12,%esp - ret - -3: fld %st(0) fstpt (%esp) - fld1 mov 8(%esp),%ax and $0x7fff,%ax - cmp $0x7fff,%ax - je 1f # x = +-inf + cmp $0x3fff+13,%ax + jb 4f # |x| < 8192 + cmp $0x3fff+15,%ax + jae 3f # |x| >= 32768 + fsts (%esp) + cmpl $0xc67ff800,(%esp) + jb 2f # x > -16382 + movl $0x5f000000,(%esp) + flds (%esp) # 0x1p63 + fld %st(1) + fsub %st(1) + faddp + fucomp %st(1) + fnstsw + sahf + je 2f # x - 0x1p63 + 0x1p63 == x + movl $1,(%esp) + flds (%esp) # 0x1p-149 + fdiv %st(1) + fstps (%esp) # raise underflow +2: fld1 fld %st(1) frndint fxch %st(2) @@ -141,3 +131,19 @@ fstp %st(1) add $12,%esp ret +3: xor %eax,%eax +4: cmp $0x3fff-64,%ax + fld1 + jb 1b # |x| < 0x1p-64 + fstpt (%esp) + fistl 8(%esp) + fildl 8(%esp) + fsubrp %st(1) + addl $0x3fff,8(%esp) + f2xm1 + fld1 + faddp # 2^(x-rint(x)) + fldt (%esp) # 2^rint(x) + fmulp + add $12,%esp + ret diff -Nur musl-0.9.13/src/math/ilogb.c musl-git/src/math/ilogb.c --- musl-0.9.13/src/math/ilogb.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/ilogb.c 2013-09-16 20:31:39.000000000 +0200 @@ -3,22 +3,24 @@ int ilogb(double x) { - union dshape u = {x}; - int e = u.bits>>52 & 0x7ff; + #pragma STDC FENV_ACCESS ON + union {double f; uint64_t i;} u = {x}; + uint64_t i = u.i; + int e = i>>52 & 0x7ff; if (!e) { - u.bits <<= 12; - if (u.bits == 0) { + i <<= 12; + if (i == 0) { FORCE_EVAL(0/0.0f); return FP_ILOGB0; } /* subnormal x */ - for (e = -0x3ff; u.bits < (uint64_t)1<<63; e--, u.bits<<=1); + for (e = -0x3ff; i>>63 == 0; e--, i<<=1); return e; } if (e == 0x7ff) { FORCE_EVAL(0/0.0f); - return u.bits<<12 ? FP_ILOGBNAN : INT_MAX; + return i<<12 ? FP_ILOGBNAN : INT_MAX; } return e - 0x3ff; } diff -Nur musl-0.9.13/src/math/ilogbf.c musl-git/src/math/ilogbf.c --- musl-0.9.13/src/math/ilogbf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/ilogbf.c 2013-09-16 20:31:39.000000000 +0200 @@ -3,22 +3,24 @@ int ilogbf(float x) { - union fshape u = {x}; - int e = u.bits>>23 & 0xff; + #pragma STDC FENV_ACCESS ON + union {float f; uint32_t i;} u = {x}; + uint32_t i = u.i; + int e = i>>23 & 0xff; if (!e) { - u.bits <<= 9; - if (u.bits == 0) { + i <<= 9; + if (i == 0) { FORCE_EVAL(0/0.0f); return FP_ILOGB0; } /* subnormal x */ - for (e = -0x7f; u.bits < (uint32_t)1<<31; e--, u.bits<<=1); + for (e = -0x7f; i>>31 == 0; e--, i<<=1); return e; } if (e == 0xff) { FORCE_EVAL(0/0.0f); - return u.bits<<9 ? FP_ILOGBNAN : INT_MAX; + return i<<9 ? FP_ILOGBNAN : INT_MAX; } return e - 0x7f; } diff -Nur musl-0.9.13/src/math/ilogbl.c musl-git/src/math/ilogbl.c --- musl-0.9.13/src/math/ilogbl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/ilogbl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,9 +9,10 @@ #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 int ilogbl(long double x) { + #pragma STDC FENV_ACCESS ON union ldshape u = {x}; - uint64_t m = u.bits.m; - int e = u.bits.exp; + uint64_t m = u.i.m; + int e = u.i.se & 0x7fff; if (!e) { if (m == 0) { @@ -19,13 +20,35 @@ return FP_ILOGB0; } /* subnormal x */ - for (e = -0x3fff+1; m < (uint64_t)1<<63; e--, m<<=1); + for (e = -0x3fff+1; m>>63 == 0; e--, m<<=1); return e; } if (e == 0x7fff) { FORCE_EVAL(0/0.0f); - /* in ld80 msb is set in inf */ - return m & (uint64_t)-1>>1 ? FP_ILOGBNAN : INT_MAX; + return m<<1 ? FP_ILOGBNAN : INT_MAX; + } + return e - 0x3fff; +} +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 +int ilogbl(long double x) +{ + #pragma STDC FENV_ACCESS ON + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + + if (!e) { + if (x == 0) { + FORCE_EVAL(0/0.0f); + return FP_ILOGB0; + } + /* subnormal x */ + x *= 0x1p120; + return ilogbl(x) - 120; + } + if (e == 0x7fff) { + FORCE_EVAL(0/0.0f); + u.i.se = 0; + return u.f ? FP_ILOGBNAN : INT_MAX; } return e - 0x3fff; } diff -Nur musl-0.9.13/src/math/lgamma_r.c musl-git/src/math/lgamma_r.c --- musl-0.9.13/src/math/lgamma_r.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/lgamma_r.c 2013-09-16 20:31:39.000000000 +0200 @@ -79,6 +79,7 @@ */ #include "libm.h" +#include "libc.h" static const double two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ diff -Nur musl-0.9.13/src/math/lgammaf_r.c musl-git/src/math/lgammaf_r.c --- musl-0.9.13/src/math/lgammaf_r.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/lgammaf_r.c 2013-09-16 20:31:39.000000000 +0200 @@ -14,6 +14,7 @@ */ #include "libm.h" +#include "libc.h" static const float two23= 8.3886080000e+06, /* 0x4b000000 */ diff -Nur musl-0.9.13/src/math/lgammal.c musl-git/src/math/lgammal.c --- musl-0.9.13/src/math/lgammal.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/lgammal.c 2013-09-16 20:31:39.000000000 +0200 @@ -87,6 +87,7 @@ #define _GNU_SOURCE #include "libm.h" +#include "libc.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 double __lgamma_r(double x, int *sg); @@ -202,13 +203,11 @@ static long double sin_pi(long double x) { + union ldshape u = {x}; + uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48; long double y, z; - int n, ix; - uint32_t se, i0, i1; + int n; - GET_LDOUBLE_WORDS(se, i0, i1, x); - ix = se & 0x7fff; - ix = (ix << 16) | (i0 >> 16); if (ix < 0x3ffd8000) /* 0.25 */ return sinl(pi * x); y = -x; /* x is assume negative */ @@ -229,8 +228,8 @@ } else { if (ix < 0x403e8000) /* 2^63 */ z = y + two63; /* exact */ - GET_LDOUBLE_WORDS(se, i0, i1, z); - n = i1 & 1; + u.f = z; + n = u.i.m & 1; y = n; n <<= 2; } @@ -261,33 +260,28 @@ long double __lgammal_r(long double x, int *sg) { long double t, y, z, nadj, p, p1, p2, q, r, w; - int i, ix; - uint32_t se, i0, i1; + union ldshape u = {x}; + uint32_t ix = (u.i.se & 0x7fffU)<<16 | u.i.m>>48; + int sign = u.i.se >> 15; + int i; *sg = 1; - GET_LDOUBLE_WORDS(se, i0, i1, x); - ix = se & 0x7fff; - - if ((ix | i0 | i1) == 0) { - if (se & 0x8000) - *sg = -1; - return 1.0 / fabsl(x); - } - - ix = (ix << 16) | (i0 >> 16); /* purge off +-inf, NaN, +-0, and negative arguments */ if (ix >= 0x7fff0000) return x * x; - + if (x == 0) { + *sg -= 2*sign; + return 1.0 / fabsl(x); + } if (ix < 0x3fc08000) { /* |x|<2**-63, return -log(|x|) */ - if (se & 0x8000) { + if (sign) { *sg = -1; return -logl(-x); } return -logl(x); } - if (se & 0x8000) { + if (sign) { t = sin_pi (x); if (t == 0.0) return 1.0 / fabsl(t); /* -integer */ @@ -297,11 +291,7 @@ x = -x; } - /* purge off 1 and 2 */ - if ((((ix - 0x3fff8000) | i0 | i1) == 0) || - (((ix - 0x40008000) | i0 | i1) == 0)) - r = 0; - else if (ix < 0x40008000) { /* x < 2.0 */ + if (ix < 0x40008000) { /* x < 2.0 */ if (ix <= 0x3ffee666) { /* 8.99993896484375e-1 */ /* lgamma(x) = lgamma(x+1) - log(x) */ r = -logl(x); @@ -380,7 +370,7 @@ r = (x - 0.5) * (t - 1.0) + w; } else /* 2**66 <= x <= inf */ r = x * (logl(x) - 1.0); - if (se & 0x8000) + if (sign) r = nadj - r; return r; } diff -Nur musl-0.9.13/src/math/log1p.c musl-git/src/math/log1p.c --- musl-0.9.13/src/math/log1p.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/log1p.c 2013-09-16 20:31:39.000000000 +0200 @@ -122,7 +122,7 @@ return x+x; if (k != 0) { if (hx < 0x43400000) { - STRICT_ASSIGN(double, u, 1.0 + x); + u = 1 + x; GET_HIGH_WORD(hu, u); k = (hu>>20) - 1023; c = k > 0 ? 1.0-(u-x) : x-(u-1.0); /* correction term */ diff -Nur musl-0.9.13/src/math/log1pf.c musl-git/src/math/log1pf.c --- musl-0.9.13/src/math/log1pf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/log1pf.c 2013-09-16 20:31:39.000000000 +0200 @@ -61,7 +61,7 @@ return x+x; if (k != 0) { if (hx < 0x5a000000) { - STRICT_ASSIGN(float, u, 1.0f + x); + u = 1 + x; GET_FLOAT_WORD(hu, u); k = (hu>>23) - 127; /* correction term */ diff -Nur musl-0.9.13/src/math/logb.c musl-git/src/math/logb.c --- musl-0.9.13/src/math/logb.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/logb.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,4 +1,4 @@ -#include "libm.h" +#include /* special cases: @@ -12,6 +12,6 @@ if (!isfinite(x)) return x * x; if (x == 0) - return -1/(x+0); + return -1/(x*x); return ilogb(x); } diff -Nur musl-0.9.13/src/math/logbf.c musl-git/src/math/logbf.c --- musl-0.9.13/src/math/logbf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/logbf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,10 @@ -#include "libm.h" +#include float logbf(float x) { if (!isfinite(x)) return x * x; if (x == 0) - return -1/(x+0); + return -1/(x*x); return ilogbf(x); } diff -Nur musl-0.9.13/src/math/logbl.c musl-git/src/math/logbl.c --- musl-0.9.13/src/math/logbl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/logbl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,4 +1,4 @@ -#include "libm.h" +#include #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 long double logbl(long double x) { @@ -10,7 +10,7 @@ if (!isfinite(x)) return x * x; if (x == 0) - return -1/(x+0); + return -1/(x*x); return ilogbl(x); } #endif diff -Nur musl-0.9.13/src/math/modf.c musl-git/src/math/modf.c --- musl-0.9.13/src/math/modf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/modf.c 2013-09-16 20:31:39.000000000 +0200 @@ -2,36 +2,33 @@ double modf(double x, double *iptr) { - union {double x; uint64_t n;} u = {x}; + union {double f; uint64_t i;} u = {x}; uint64_t mask; - int e; - - e = (int)(u.n>>52 & 0x7ff) - 0x3ff; + int e = (int)(u.i>>52 & 0x7ff) - 0x3ff; /* no fractional part */ if (e >= 52) { *iptr = x; - if (e == 0x400 && u.n<<12 != 0) /* nan */ + if (e == 0x400 && u.i<<12 != 0) /* nan */ return x; - u.n &= (uint64_t)1<<63; - return u.x; + u.i &= 1ULL<<63; + return u.f; } /* no integral part*/ if (e < 0) { - u.n &= (uint64_t)1<<63; - *iptr = u.x; + u.i &= 1ULL<<63; + *iptr = u.f; return x; } - mask = (uint64_t)-1>>12 >> e; - if ((u.n & mask) == 0) { + mask = -1ULL>>12>>e; + if ((u.i & mask) == 0) { *iptr = x; - u.n &= (uint64_t)1<<63; - return u.x; + u.i &= 1ULL<<63; + return u.f; } - u.n &= ~mask; - *iptr = u.x; - STRICT_ASSIGN(double, x, x - *iptr); - return x; + u.i &= ~mask; + *iptr = u.f; + return x - u.f; } diff -Nur musl-0.9.13/src/math/modff.c musl-git/src/math/modff.c --- musl-0.9.13/src/math/modff.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/modff.c 2013-09-16 20:31:39.000000000 +0200 @@ -2,36 +2,33 @@ float modff(float x, float *iptr) { - union {float x; uint32_t n;} u = {x}; + union {float f; uint32_t i;} u = {x}; uint32_t mask; - int e; - - e = (int)(u.n>>23 & 0xff) - 0x7f; + int e = (int)(u.i>>23 & 0xff) - 0x7f; /* no fractional part */ if (e >= 23) { *iptr = x; - if (e == 0x80 && u.n<<9 != 0) { /* nan */ + if (e == 0x80 && u.i<<9 != 0) { /* nan */ return x; } - u.n &= 0x80000000; - return u.x; + u.i &= 0x80000000; + return u.f; } /* no integral part */ if (e < 0) { - u.n &= 0x80000000; - *iptr = u.x; + u.i &= 0x80000000; + *iptr = u.f; return x; } mask = 0x007fffff>>e; - if ((u.n & mask) == 0) { + if ((u.i & mask) == 0) { *iptr = x; - u.n &= 0x80000000; - return u.x; + u.i &= 0x80000000; + return u.f; } - u.n &= ~mask; - *iptr = u.x; - STRICT_ASSIGN(float, x, x - *iptr); - return x; + u.i &= ~mask; + *iptr = u.f; + return x - u.f; } diff -Nur musl-0.9.13/src/math/modfl.c musl-git/src/math/modfl.c --- musl-0.9.13/src/math/modfl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/modfl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,40 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_modfl.c */ -/*- - * Copyright (c) 2007 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Derived from s_modf.c, which has the following Copyright: - * ==================================================== - * 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 "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -43,58 +6,46 @@ return modf(x, (double *)iptr); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#if LDBL_MANL_SIZE > 32 -#define MASK ((uint64_t)-1) -#else -#define MASK ((uint32_t)-1) +#if LDBL_MANT_DIG == 64 +#define TOINT 0x1p63 +#elif LDBL_MANT_DIG == 113 +#define TOINT 0x1p112 #endif -/* Return the last n bits of a word, representing the fractional part. */ -#define GETFRAC(bits, n) ((bits) & ~(MASK << (n))) -/* The number of fraction bits in manh, not counting the integer bit */ -#define HIBITS (LDBL_MANT_DIG - LDBL_MANL_SIZE) - -static const long double zero[] = { 0.0, -0.0 }; - long double modfl(long double x, long double *iptr) { - union IEEEl2bits ux; - int e; + union ldshape u = {x}; + uint64_t mask; + int e = (u.i.se & 0x7fff) - 0x3fff; + int s = u.i.se >> 15; + long double absx; + long double y; - ux.e = x; - e = ux.bits.exp - LDBL_MAX_EXP + 1; - if (e < HIBITS) { /* Integer part is in manh. */ - if (e < 0) { /* |x|<1 */ - *iptr = zero[ux.bits.sign]; - return x; - } - if ((GETFRAC(ux.bits.manh, HIBITS - 1 - e)|ux.bits.manl) == 0) { - /* x is an integer. */ - *iptr = x; - return zero[ux.bits.sign]; - } - /* Clear all but the top e+1 bits. */ - ux.bits.manh >>= HIBITS - 1 - e; - ux.bits.manh <<= HIBITS - 1 - e; - ux.bits.manl = 0; - *iptr = ux.e; - return x - ux.e; - } else if (e >= LDBL_MANT_DIG - 1) { /* x has no fraction part. */ + /* no fractional part */ + if (e >= LDBL_MANT_DIG-1) { *iptr = x; - if (e == LDBL_MAX_EXP && ((ux.bits.manh&~LDBL_NBIT)|ux.bits.manl)) /* nan */ + if (isnan(x)) return x; - return zero[ux.bits.sign]; - } else { /* Fraction part is in manl. */ - if (GETFRAC(ux.bits.manl, LDBL_MANT_DIG - 1 - e) == 0) { - /* x is integral. */ - *iptr = x; - return zero[ux.bits.sign]; - } - /* Clear all but the top e+1 bits. */ - ux.bits.manl >>= LDBL_MANT_DIG - 1 - e; - ux.bits.manl <<= LDBL_MANT_DIG - 1 - e; - *iptr = ux.e; - return x - ux.e; + return s ? -0.0 : 0.0; + } + + /* no integral part*/ + if (e < 0) { + *iptr = s ? -0.0 : 0.0; + return x; + } + + /* raises spurious inexact */ + absx = s ? -x : x; + y = absx + TOINT - TOINT - absx; + if (y == 0) { + *iptr = x; + return s ? -0.0 : 0.0; } + if (y > 0) + y -= 1; + if (s) + y = -y; + *iptr = x + y; + return -y; } #endif diff -Nur musl-0.9.13/src/math/nextafter.c musl-git/src/math/nextafter.c --- musl-0.9.13/src/math/nextafter.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/nextafter.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,35 +1,31 @@ #include "libm.h" -#define SIGN ((uint64_t)1<<63) - double nextafter(double x, double y) { - union dshape ux, uy; + union {double f; uint64_t i;} ux={x}, uy={y}; uint64_t ax, ay; int e; if (isnan(x) || isnan(y)) return x + y; - ux.value = x; - uy.value = y; - if (ux.bits == uy.bits) + if (ux.i == uy.i) return y; - ax = ux.bits & ~SIGN; - ay = uy.bits & ~SIGN; + ax = ux.i & -1ULL/2; + ay = uy.i & -1ULL/2; if (ax == 0) { if (ay == 0) return y; - ux.bits = (uy.bits & SIGN) | 1; - } else if (ax > ay || ((ux.bits ^ uy.bits) & SIGN)) - ux.bits--; + ux.i = (uy.i & 1ULL<<63) | 1; + } else if (ax > ay || ((ux.i ^ uy.i) & 1ULL<<63)) + ux.i--; else - ux.bits++; - e = ux.bits >> 52 & 0x7ff; - /* raise overflow if ux.value is infinite and x is finite */ + ux.i++; + e = ux.i >> 52 & 0x7ff; + /* raise overflow if ux.f is infinite and x is finite */ if (e == 0x7ff) FORCE_EVAL(x+x); - /* raise underflow if ux.value is subnormal or zero */ + /* raise underflow if ux.f is subnormal or zero */ if (e == 0) - FORCE_EVAL(x*x + ux.value*ux.value); - return ux.value; + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; } diff -Nur musl-0.9.13/src/math/nextafterf.c musl-git/src/math/nextafterf.c --- musl-0.9.13/src/math/nextafterf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/nextafterf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,34 +1,30 @@ #include "libm.h" -#define SIGN 0x80000000 - float nextafterf(float x, float y) { - union fshape ux, uy; + union {float f; uint32_t i;} ux={x}, uy={y}; uint32_t ax, ay, e; if (isnan(x) || isnan(y)) return x + y; - ux.value = x; - uy.value = y; - if (ux.bits == uy.bits) + if (ux.i == uy.i) return y; - ax = ux.bits & ~SIGN; - ay = uy.bits & ~SIGN; + ax = ux.i & 0x7fffffff; + ay = uy.i & 0x7fffffff; if (ax == 0) { if (ay == 0) return y; - ux.bits = (uy.bits & SIGN) | 1; - } else if (ax > ay || ((ux.bits ^ uy.bits) & SIGN)) - ux.bits--; + ux.i = (uy.i & 0x80000000) | 1; + } else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000)) + ux.i--; else - ux.bits++; - e = ux.bits & 0x7f800000; - /* raise overflow if ux.value is infinite and x is finite */ + ux.i++; + e = ux.i & 0x7f800000; + /* raise overflow if ux.f is infinite and x is finite */ if (e == 0x7f800000) FORCE_EVAL(x+x); - /* raise underflow if ux.value is subnormal or zero */ + /* raise underflow if ux.f is subnormal or zero */ if (e == 0) - FORCE_EVAL(x*x + ux.value*ux.value); - return ux.value; + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; } diff -Nur musl-0.9.13/src/math/nextafterl.c musl-git/src/math/nextafterl.c --- musl-0.9.13/src/math/nextafterl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/nextafterl.c 2013-09-16 20:31:39.000000000 +0200 @@ -6,7 +6,6 @@ return nextafter(x, y); } #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 -#define MSB ((uint64_t)1<<63) long double nextafterl(long double x, long double y) { union ldshape ux, uy; @@ -15,32 +14,32 @@ return x + y; if (x == y) return y; - ux.value = x; + ux.f = x; if (x == 0) { - uy.value = y; - ux.bits.m = 1; - ux.bits.sign = uy.bits.sign; - } else if (x < y ^ ux.bits.sign) { - ux.bits.m++; - if ((ux.bits.m & ~MSB) == 0) { - ux.bits.m = MSB; - ux.bits.exp++; + uy.f = y; + ux.i.m = 1; + ux.i.se = uy.i.se & 0x8000; + } else if ((x < y) == !(ux.i.se & 0x8000)) { + ux.i.m++; + if (ux.i.m << 1 == 0) { + ux.i.m = 1ULL << 63; + ux.i.se++; } } else { - if ((ux.bits.m & ~MSB) == 0) { - ux.bits.exp--; - if (ux.bits.exp) - ux.bits.m = 0; + if (ux.i.m << 1 == 0) { + ux.i.se--; + if (ux.i.se) + ux.i.m = 0; } - ux.bits.m--; + ux.i.m--; } - /* raise overflow if ux.value is infinite and x is finite */ - if (ux.bits.exp == 0x7fff) + /* raise overflow if ux is infinite and x is finite */ + if ((ux.i.se & 0x7fff) == 0x7fff) return x + x; - /* raise underflow if ux.value is subnormal or zero */ - if (ux.bits.exp == 0) - FORCE_EVAL(x*x + ux.value*ux.value); - return ux.value; + /* raise underflow if ux is subnormal or zero */ + if ((ux.i.se & 0x7fff) == 0) + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; } #elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 long double nextafterl(long double x, long double y) @@ -51,32 +50,26 @@ return x + y; if (x == y) return y; - ux.value = x; + ux.f = x; if (x == 0) { - uy.value = y; - ux.bits.mlo = 1; - ux.bits.sign = uy.bits.sign; - } else if (x < y ^ ux.bits.sign) { - ux.bits.mlo++; - if (ux.bits.mlo == 0) { - ux.bits.mhi++; - if (ux.bits.mhi == 0) - ux.bits.exp++; - } + uy.f = y; + ux.i.lo = 1; + ux.i.se = uy.i.se & 0x8000; + } else if ((x < y) == !(ux.i.se & 0x8000)) { + ux.i2.lo++; + if (ux.i2.lo == 0) + ux.i2.hi++; } else { - if (ux.bits.mlo == 0) { - if (ux.bits.mhi == 0) - ux.bits.exp--; - ux.bits.mhi--; - } - ux.bits.mlo--; + if (ux.i2.lo == 0) + ux.i2.hi--; + ux.i2.lo--; } - /* raise overflow if ux.value is infinite and x is finite */ - if (ux.bits.exp == 0x7fff) + /* raise overflow if ux is infinite and x is finite */ + if ((ux.i.se & 0x7fff) == 0x7fff) return x + x; - /* raise underflow if ux.value is subnormal or zero */ - if (ux.bits.exp == 0) - FORCE_EVAL(x*x + ux.value*ux.value); - return ux.value; + /* raise underflow if ux is subnormal or zero */ + if ((ux.i.se & 0x7fff) == 0) + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; } #endif diff -Nur musl-0.9.13/src/math/nexttoward.c musl-git/src/math/nexttoward.c --- musl-0.9.13/src/math/nexttoward.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/nexttoward.c 2013-09-16 20:31:39.000000000 +0200 @@ -6,40 +6,37 @@ return nextafter(x, y); } #else -#define SIGN ((uint64_t)1<<63) - double nexttoward(double x, long double y) { - union dshape ux; + union {double f; uint64_t i;} ux = {x}; int e; if (isnan(x) || isnan(y)) return x + y; if (x == y) return y; - ux.value = x; if (x == 0) { - ux.bits = 1; + ux.i = 1; if (signbit(y)) - ux.bits |= SIGN; + ux.i |= 1ULL<<63; } else if (x < y) { if (signbit(x)) - ux.bits--; + ux.i--; else - ux.bits++; + ux.i++; } else { if (signbit(x)) - ux.bits++; + ux.i++; else - ux.bits--; + ux.i--; } - e = ux.bits>>52 & 0x7ff; - /* raise overflow if ux.value is infinite and x is finite */ + e = ux.i>>52 & 0x7ff; + /* raise overflow if ux.f is infinite and x is finite */ if (e == 0x7ff) FORCE_EVAL(x+x); - /* raise underflow if ux.value is subnormal or zero */ + /* raise underflow if ux.f is subnormal or zero */ if (e == 0) - FORCE_EVAL(x*x + ux.value*ux.value); - return ux.value; + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; } #endif diff -Nur musl-0.9.13/src/math/nexttowardf.c musl-git/src/math/nexttowardf.c --- musl-0.9.13/src/math/nexttowardf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/nexttowardf.c 2013-09-16 20:31:39.000000000 +0200 @@ -2,35 +2,34 @@ float nexttowardf(float x, long double y) { - union fshape ux; + union {float f; uint32_t i;} ux = {x}; uint32_t e; if (isnan(x) || isnan(y)) return x + y; if (x == y) return y; - ux.value = x; if (x == 0) { - ux.bits = 1; + ux.i = 1; if (signbit(y)) - ux.bits |= 0x80000000; + ux.i |= 0x80000000; } else if (x < y) { if (signbit(x)) - ux.bits--; + ux.i--; else - ux.bits++; + ux.i++; } else { if (signbit(x)) - ux.bits++; + ux.i++; else - ux.bits--; + ux.i--; } - e = ux.bits & 0x7f800000; - /* raise overflow if ux.value is infinite and x is finite */ + e = ux.i & 0x7f800000; + /* raise overflow if ux.f is infinite and x is finite */ if (e == 0x7f800000) FORCE_EVAL(x+x); - /* raise underflow if ux.value is subnormal or zero */ + /* raise underflow if ux.f is subnormal or zero */ if (e == 0) - FORCE_EVAL(x*x + ux.value*ux.value); - return ux.value; + FORCE_EVAL(x*x + ux.f*ux.f); + return ux.f; } diff -Nur musl-0.9.13/src/math/remainder.c musl-git/src/math/remainder.c --- musl-0.9.13/src/math/remainder.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/remainder.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,66 +1,7 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_remainder.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* remainder(x,p) - * Return : - * returns x REM p = x - [x/p]*p as if in infinite - * precise arithmetic, where [x/p] is the (infinite bit) - * integer nearest x/p (in half way case choose the even one). - * Method : - * Based on fmod() return x-[x/p]chopped*p exactlp. - */ +#include -#include "libm.h" - -double remainder(double x, double p) +double remainder(double x, double y) { - int32_t hx,hp; - uint32_t sx,lx,lp; - double p_half; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hp, lp, p); - sx = hx & 0x80000000; - hp &= 0x7fffffff; - hx &= 0x7fffffff; - - /* purge off exception values */ - if ((hp|lp) == 0 || /* p = 0 */ - hx >= 0x7ff00000 || /* x not finite */ - (hp >= 0x7ff00000 && (hp-0x7ff00000 | lp) != 0)) /* p is NaN */ - return (x*p)/(x*p); - - if (hp <= 0x7fdfffff) - x = fmod(x, p+p); /* now x < 2p */ - if (((hx-hp)|(lx-lp)) == 0) - return 0.0*x; - x = fabs(x); - p = fabs(p); - if (hp < 0x00200000) { - if (x + x > p) { - x -= p; - if (x + x >= p) - x -= p; - } - } else { - p_half = 0.5*p; - if (x > p_half) { - x -= p; - if (x >= p_half) - x -= p; - } - } - GET_HIGH_WORD(hx, x); - if ((hx&0x7fffffff) == 0) - hx = 0; - SET_HIGH_WORD(x, hx^sx); - return x; + int q; + return remquo(x, y, &q); } diff -Nur musl-0.9.13/src/math/remainderf.c musl-git/src/math/remainderf.c --- musl-0.9.13/src/math/remainderf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/remainderf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,59 +1,7 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/e_remainderf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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 -#include "libm.h" - -float remainderf(float x, float p) +float remainderf(float x, float y) { - int32_t hx,hp; - uint32_t sx; - float p_half; - - GET_FLOAT_WORD(hx, x); - GET_FLOAT_WORD(hp, p); - sx = hx & 0x80000000; - hp &= 0x7fffffff; - hx &= 0x7fffffff; - - /* purge off exception values */ - if (hp == 0 || hx >= 0x7f800000 || hp > 0x7f800000) /* p = 0, x not finite, p is NaN */ - return (x*p)/(x*p); - - if (hp <= 0x7effffff) - x = fmodf(x, p + p); /* now x < 2p */ - if (hx - hp == 0) - return 0.0f*x; - x = fabsf(x); - p = fabsf(p); - if (hp < 0x01000000) { - if (x + x > p) { - x -= p; - if (x + x >= p) - x -= p; - } - } else { - p_half = 0.5f*p; - if (x > p_half) { - x -= p; - if (x >= p_half) - x -= p; - } - } - GET_FLOAT_WORD(hx, x); - if ((hx & 0x7fffffff) == 0) - hx = 0; - SET_FLOAT_WORD(x, hx ^ sx); - return x; + int q; + return remquof(x, y, &q); } diff -Nur musl-0.9.13/src/math/remquo.c musl-git/src/math/remquo.c --- musl-0.9.13/src/math/remquo.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/remquo.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,171 +1,82 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_remquo.c */ -/*- - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * Return the IEEE remainder and set *quo to the last n bits of the - * quotient, rounded to the nearest integer. We choose n=31 because - * we wind up computing all the integer bits of the quotient anyway as - * a side-effect of computing the remainder by the shift and subtract - * method. In practice, this is far more bits than are needed to use - * remquo in reduction algorithms. - */ - -#include "libm.h" - -static const double Zero[] = {0.0, -0.0,}; +#include +#include double remquo(double x, double y, int *quo) { - int32_t n,hx,hy,hz,ix,iy,sx,i; - uint32_t lx,ly,lz,q,sxy; - - EXTRACT_WORDS(hx, lx, x); - EXTRACT_WORDS(hy, ly, y); - sxy = (hx ^ hy) & 0x80000000; - sx = hx & 0x80000000; /* sign of x */ - hx ^= sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ + union {double f; uint64_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>52 & 0x7ff; + int ey = uy.i>>52 & 0x7ff; + int sx = ux.i>>63; + int sy = uy.i>>63; + uint32_t q; + uint64_t i; + uint64_t uxi = ux.i; - /* purge off exception values */ - if ((hy|ly) == 0 || hx >= 0x7ff00000 || /* y = 0, or x not finite */ - (hy|((ly|-ly)>>31)) > 0x7ff00000) /* or y is NaN */ + *quo = 0; + if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff) return (x*y)/(x*y); - if (hx <= hy) { - if (hx < hy || lx < ly) { /* |x| < |y| return x or x-y */ - q = 0; - goto fixup; - } - if (lx == ly) { /* |x| = |y| return x*0 */ - *quo = sxy ? -1 : 1; - return Zero[(uint32_t)sx>>31]; - } - } + if (ux.i<<1 == 0) + return x; - // FIXME: use ilogb? - - /* determine ix = ilogb(x) */ - if (hx < 0x00100000) { /* subnormal x */ - if (hx == 0) { - for (ix = -1043, i=lx; i>0; i<<=1) ix--; - } else { - for (ix = -1022, i=hx<<11; i>0; i<<=1) ix--; - } - } else - ix = (hx>>20) - 1023; - - /* determine iy = ilogb(y) */ - if (hy < 0x00100000) { /* subnormal y */ - if (hy == 0) { - for (iy = -1043, i=ly; i>0; i<<=1) iy--; - } else { - for (iy = -1022, i=hy<<11; i>0; i<<=1) iy--; - } - } else - iy = (hy>>20) - 1023; - - /* set up {hx,lx}, {hy,ly} and align y to x */ - if (ix >= -1022) - hx = 0x00100000|(0x000fffff&hx); - else { /* subnormal x, shift x to normal */ - n = -1022 - ix; - if (n <= 31) { - hx = (hx<>(32-n)); - lx <<= n; - } else { - hx = lx<<(n-32); - lx = 0; - } - } - if (iy >= -1022) - hy = 0x00100000|(0x000fffff&hy); - else { /* subnormal y, shift y to normal */ - n = -1022 - iy; - if (n <= 31) { - hy = (hy<>(32-n)); - ly <<= n; - } else { - hy = ly<<(n-32); - ly = 0; - } + /* normalize x and y */ + if (!ex) { + for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1ULL >> 12; + uxi |= 1ULL << 52; + } + if (!ey) { + for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1ULL >> 12; + uy.i |= 1ULL << 52; } - /* fix point fmod */ - n = ix - iy; q = 0; - while (n--) { - hz = hx - hy; - lz = lx - ly; - if (lx < ly) - hz--; - if (hz < 0) { - hx = hx + hx + (lx>>31); - lx = lx + lx; - } else { - hx = hz + hz + (lz>>31); - lx = lz + lz; + if (ex < ey) { + if (ex+1 == ey) + goto end; + return x; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 63 == 0) { + uxi = i; q++; } + uxi <<= 1; q <<= 1; } - hz = hx - hy; - lz = lx - ly; - if (lx < ly) - hz--; - if (hz >= 0) { - hx = hz; - lx = lz; + i = uxi - uy.i; + if (i >> 63 == 0) { + uxi = i; q++; } - - /* convert back to floating value and restore the sign */ - if ((hx|lx) == 0) { /* return sign(x)*0 */ - q &= 0x7fffffff; - *quo = sxy ? -q : q; - return Zero[(uint32_t)sx>>31]; - } - while (hx < 0x00100000) { /* normalize x */ - hx = hx + hx + (lx>>31); - lx = lx + lx; - iy--; - } - if (iy >= -1022) { /* normalize output */ - hx = (hx-0x00100000)|((iy+1023)<<20); - } else { /* subnormal output */ - n = -1022 - iy; - if (n <= 20) { - lx = (lx>>n)|((uint32_t)hx<<(32-n)); - hx >>= n; - } else if (n <= 31) { - lx = (hx<<(32-n))|(lx>>n); - hx = 0; - } else { - lx = hx>>(n-32); - hx = 0; - } - } -fixup: - INSERT_WORDS(x, hx, lx); - y = fabs(y); - if (y < 0x1p-1021) { - if (x + x > y || (x + x == y && (q & 1))) { - q++; - x -= y; - } - } else if (x > 0.5*y || (x == 0.5*y && (q & 1))) { - q++; + if (uxi == 0) + ex = -60; + else + for (; uxi>>52 == 0; uxi <<= 1, ex--); +end: + /* scale result and decide between |x| and |x|-|y| */ + if (ex > 0) { + uxi -= 1ULL << 52; + uxi |= (uint64_t)ex << 52; + } else { + uxi >>= -ex + 1; + } + ux.i = uxi; + x = ux.f; + if (sy) + y = -y; + if (ex == ey || (ex+1 == ey && (2*x > y || (2*x == y && q%2)))) { x -= y; + q++; } - GET_HIGH_WORD(hx, x); - SET_HIGH_WORD(x, hx ^ sx); q &= 0x7fffffff; - *quo = sxy ? -q : q; - return x; + *quo = sx^sy ? -(int)q : (int)q; + return sx ? -x : x; } diff -Nur musl-0.9.13/src/math/remquof.c musl-git/src/math/remquof.c --- musl-0.9.13/src/math/remquof.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/remquof.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,126 +1,82 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_remquof.c */ -/*- - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* - * Return the IEEE remainder and set *quo to the last n bits of the - * quotient, rounded to the nearest integer. We choose n=31 because - * we wind up computing all the integer bits of the quotient anyway as - * a side-effect of computing the remainder by the shift and subtract - * method. In practice, this is far more bits than are needed to use - * remquo in reduction algorithms. - */ - -#include "libm.h" - -static const float Zero[] = {0.0, -0.0,}; +#include +#include float remquof(float x, float y, int *quo) { - int32_t n,hx,hy,hz,ix,iy,sx,i; - uint32_t q,sxy; + union {float f; uint32_t i;} ux = {x}, uy = {y}; + int ex = ux.i>>23 & 0xff; + int ey = uy.i>>23 & 0xff; + int sx = ux.i>>31; + int sy = uy.i>>31; + uint32_t q; + uint32_t i; + uint32_t uxi = ux.i; - GET_FLOAT_WORD(hx, x); - GET_FLOAT_WORD(hy, y); - sxy = (hx ^ hy) & 0x80000000; - sx = hx & 0x80000000; /* sign of x */ - hx ^= sx; /* |x| */ - hy &= 0x7fffffff; /* |y| */ - - /* purge off exception values */ - if (hy == 0 || hx >= 0x7f800000 || hy > 0x7f800000) /* y=0,NaN;or x not finite */ + *quo = 0; + if (uy.i<<1 == 0 || isnan(y) || ex == 0xff) return (x*y)/(x*y); - if (hx < hy) { /* |x| < |y| return x or x-y */ - q = 0; - goto fixup; - } else if(hx==hy) { /* |x| = |y| return x*0*/ - *quo = sxy ? -1 : 1; - return Zero[(uint32_t)sx>>31]; - } + if (ux.i<<1 == 0) + return x; - /* determine ix = ilogb(x) */ - if (hx < 0x00800000) { /* subnormal x */ - for (ix = -126, i=hx<<8; i>0; i<<=1) ix--; - } else - ix = (hx>>23) - 127; - - /* determine iy = ilogb(y) */ - if (hy < 0x00800000) { /* subnormal y */ - for (iy = -126, i=hy<<8; i>0; i<<=1) iy--; - } else - iy = (hy>>23) - 127; - - /* set up {hx,lx}, {hy,ly} and align y to x */ - if (ix >= -126) - hx = 0x00800000|(0x007fffff&hx); - else { /* subnormal x, shift x to normal */ - n = -126 - ix; - hx <<= n; - } - if (iy >= -126) - hy = 0x00800000|(0x007fffff&hy); - else { /* subnormal y, shift y to normal */ - n = -126 - iy; - hy <<= n; + /* normalize x and y */ + if (!ex) { + for (i = uxi<<9; i>>31 == 0; ex--, i <<= 1); + uxi <<= -ex + 1; + } else { + uxi &= -1U >> 9; + uxi |= 1U << 23; + } + if (!ey) { + for (i = uy.i<<9; i>>31 == 0; ey--, i <<= 1); + uy.i <<= -ey + 1; + } else { + uy.i &= -1U >> 9; + uy.i |= 1U << 23; } - /* fix point fmod */ - n = ix - iy; q = 0; - while (n--) { - hz = hx - hy; - if (hz < 0) - hx = hx << 1; - else { - hx = hz << 1; + if (ex < ey) { + if (ex+1 == ey) + goto end; + return x; + } + + /* x mod y */ + for (; ex > ey; ex--) { + i = uxi - uy.i; + if (i >> 31 == 0) { + uxi = i; q++; } + uxi <<= 1; q <<= 1; } - hz = hx - hy; - if (hz >= 0) { - hx = hz; + i = uxi - uy.i; + if (i >> 31 == 0) { + uxi = i; q++; } - - /* convert back to floating value and restore the sign */ - if (hx == 0) { /* return sign(x)*0 */ - q &= 0x7fffffff; - *quo = sxy ? -q : q; - return Zero[(uint32_t)sx>>31]; - } - while (hx < 0x00800000) { /* normalize x */ - hx <<= 1; - iy--; - } - if (iy >= -126) { /* normalize output */ - hx = (hx-0x00800000)|((iy+127)<<23); - } else { /* subnormal output */ - n = -126 - iy; - hx >>= n; - } -fixup: - SET_FLOAT_WORD(x,hx); - y = fabsf(y); - if (y < 0x1p-125f) { - if (x + x > y || (x + x == y && (q & 1))) { - q++; - x -= y; - } - } else if (x > 0.5f*y || (x == 0.5f*y && (q & 1))) { - q++; + if (uxi == 0) + ex = -30; + else + for (; uxi>>23 == 0; uxi <<= 1, ex--); +end: + /* scale result and decide between |x| and |x|-|y| */ + if (ex > 0) { + uxi -= 1U << 23; + uxi |= (uint32_t)ex << 23; + } else { + uxi >>= -ex + 1; + } + ux.i = uxi; + x = ux.f; + if (sy) + y = -y; + if (ex == ey || (ex+1 == ey && (2*x > y || (2*x == y && q%2)))) { x -= y; + q++; } - GET_FLOAT_WORD(hx, x); - SET_FLOAT_WORD(x, hx ^ sx); q &= 0x7fffffff; - *quo = sxy ? -q : q; - return x; + *quo = sx^sy ? -(int)q : (int)q; + return sx ? -x : x; } diff -Nur musl-0.9.13/src/math/remquol.c musl-git/src/math/remquol.c --- musl-0.9.13/src/math/remquol.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/remquol.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,15 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_remquol.c */ -/*- - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -18,177 +6,119 @@ return remquo(x, y, quo); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#define BIAS (LDBL_MAX_EXP - 1) - -#if LDBL_MANL_SIZE > 32 -typedef uint64_t manl_t; -#else -typedef uint32_t manl_t; -#endif - -#if LDBL_MANH_SIZE > 32 -typedef uint64_t manh_t; -#else -typedef uint32_t manh_t; -#endif - -/* - * These macros add and remove an explicit integer bit in front of the - * fractional mantissa, if the architecture doesn't have such a bit by - * default already. - */ -#ifdef LDBL_IMPLICIT_NBIT -#define SET_NBIT(hx) ((hx) | (1ULL << LDBL_MANH_SIZE)) -#define HFRAC_BITS LDBL_MANH_SIZE -#else -#define SET_NBIT(hx) (hx) -#define HFRAC_BITS (LDBL_MANH_SIZE - 1) -#endif - -#define MANL_SHIFT (LDBL_MANL_SIZE - 1) - -static const long double Zero[] = {0.0, -0.0}; - -/* - * Return the IEEE remainder and set *quo to the last n bits of the - * quotient, rounded to the nearest integer. We choose n=31 because - * we wind up computing all the integer bits of the quotient anyway as - * a side-effect of computing the remainder by the shift and subtract - * method. In practice, this is far more bits than are needed to use - * remquo in reduction algorithms. - * - * Assumptions: - * - The low part of the mantissa fits in a manl_t exactly. - * - The high part of the mantissa fits in an int64_t with enough room - * for an explicit integer bit in front of the fractional bits. - */ long double remquol(long double x, long double y, int *quo) { - union IEEEl2bits ux, uy; - int64_t hx,hz; /* We need a carry bit even if LDBL_MANH_SIZE is 32. */ - manh_t hy; - manl_t lx,ly,lz; - int ix,iy,n,q,sx,sxy; + union ldshape ux = {x}, uy = {y}; + int ex = ux.i.se & 0x7fff; + int ey = uy.i.se & 0x7fff; + int sx = ux.i.se >> 15; + int sy = uy.i.se >> 15; + uint32_t q; - ux.e = x; - uy.e = y; - sx = ux.bits.sign; - sxy = sx ^ uy.bits.sign; - ux.bits.sign = 0; /* |x| */ - uy.bits.sign = 0; /* |y| */ - x = ux.e; - - /* purge off exception values */ - if ((uy.bits.exp|uy.bits.manh|uy.bits.manl)==0 || /* y=0 */ - (ux.bits.exp == BIAS + LDBL_MAX_EXP) || /* or x not finite */ - (uy.bits.exp == BIAS + LDBL_MAX_EXP && - ((uy.bits.manh&~LDBL_NBIT)|uy.bits.manl)!=0)) /* or y is NaN */ + *quo = 0; + if (y == 0 || isnan(y) || ex == 0x7fff) return (x*y)/(x*y); - if (ux.bits.exp <= uy.bits.exp) { - if ((ux.bits.exp < uy.bits.exp) || - (ux.bits.manh <= uy.bits.manh && - (ux.bits.manh < uy.bits.manh || - ux.bits.manl < uy.bits.manl))) { - q = 0; - goto fixup; /* |x|<|y| return x or x-y */ - } - if (ux.bits.manh == uy.bits.manh && ux.bits.manl == uy.bits.manl) { - *quo = sxy ? -1 : 1; - return Zero[sx]; /* |x|=|y| return x*0*/ - } - } - - /* determine ix = ilogb(x) */ - if (ux.bits.exp == 0) { /* subnormal x */ - ux.e *= 0x1.0p512; - ix = ux.bits.exp - (BIAS + 512); - } else { - ix = ux.bits.exp - BIAS; - } + if (x == 0) + return x; - /* determine iy = ilogb(y) */ - if (uy.bits.exp == 0) { /* subnormal y */ - uy.e *= 0x1.0p512; - iy = uy.bits.exp - (BIAS + 512); - } else { - iy = uy.bits.exp - BIAS; + /* normalize x and y */ + if (!ex) { + ux.i.se = ex; + ux.f *= 0x1p120f; + ex = ux.i.se - 120; + } + if (!ey) { + uy.i.se = ey; + uy.f *= 0x1p120f; + ey = uy.i.se - 120; } - /* set up {hx,lx}, {hy,ly} and align y to x */ - hx = SET_NBIT(ux.bits.manh); - hy = SET_NBIT(uy.bits.manh); - lx = ux.bits.manl; - ly = uy.bits.manl; - - /* fix point fmod */ - n = ix - iy; q = 0; - - while (n--) { - hz = hx - hy; - lz = lx - ly; - if (lx < ly) - hz -= 1; - if (hz < 0) { - hx = hx + hx + (lx>>MANL_SHIFT); - lx = lx + lx; - } else { - hx = hz + hz + (lz>>MANL_SHIFT); - lx = lz + lz; + if (ex >= ey) { + /* x mod y */ +#if LDBL_MANT_DIG == 64 + uint64_t i, mx, my; + mx = ux.i.m; + my = uy.i.m; + for (; ex > ey; ex--) { + i = mx - my; + if (mx >= my) { + mx = 2*i; + q++; + q <<= 1; + } else if (2*mx < mx) { + mx = 2*mx - my; + q <<= 1; + q++; + } else { + mx = 2*mx; + q <<= 1; + } + } + i = mx - my; + if (mx >= my) { + mx = i; q++; } - q <<= 1; - } - hz = hx - hy; - lz = lx - ly; - if (lx < ly) - hz -= 1; - if (hz >= 0) { - hx = hz; - lx = lz; - q++; - } - - /* convert back to floating value and restore the sign */ - if ((hx|lx) == 0) { /* return sign(x)*0 */ - q &= 0x7fffffff; - *quo = sxy ? -q : q; - return Zero[sx]; - } - while (hx < (1ULL<>MANL_SHIFT); - lx = lx + lx; - iy -= 1; - } - ux.bits.manh = hx; /* The integer bit is truncated here if needed. */ - ux.bits.manl = lx; - if (iy < LDBL_MIN_EXP) { - ux.bits.exp = iy + (BIAS + 512); - ux.e *= 0x1p-512; - } else { - ux.bits.exp = iy + BIAS; - } - ux.bits.sign = 0; - x = ux.e; -fixup: - y = fabsl(y); - if (y < LDBL_MIN * 2) { - if (x + x > y || (x + x == y && (q & 1))) { + if (mx == 0) + ex = -120; + else + for (; mx >> 63 == 0; mx *= 2, ex--); + ux.i.m = mx; +#elif LDBL_MANT_DIG == 113 + uint64_t hi, lo, xhi, xlo, yhi, ylo; + xhi = (ux.i2.hi & -1ULL>>16) | 1ULL<<48; + yhi = (uy.i2.hi & -1ULL>>16) | 1ULL<<48; + xlo = ux.i2.lo; + ylo = ux.i2.lo; + for (; ex > ey; ex--) { + hi = xhi - yhi; + lo = xlo - ylo; + if (xlo < ylo) + hi -= 1; + if (hi >> 63 == 0) { + xhi = 2*hi + (lo>>63); + xlo = 2*lo; + q++; + } else { + xhi = 2*xhi + (xlo>>63); + xlo = 2*xlo; + } + q <<= 1; + } + hi = xhi - yhi; + lo = xlo - ylo; + if (xlo < ylo) + hi -= 1; + if (hi >> 63 == 0) { + xhi = hi; + xlo = lo; q++; - x-=y; } - } else if (x > 0.5*y || (x == 0.5*y && (q & 1))) { - q++; - x-=y; + if ((xhi|xlo) == 0) + ex = -120; + else + for (; xhi >> 48 == 0; xhi = 2*xhi + (xlo>>63), xlo = 2*xlo, ex--); + ux.i2.hi = xhi; + ux.i2.lo = xlo; +#endif } - ux.e = x; - ux.bits.sign ^= sx; - x = ux.e; - + /* scale result and decide between |x| and |x|-|y| */ + if (ex <= 0) { + ux.i.se = ex + 120; + ux.f *= 0x1p-120f; + } else + ux.i.se = ex; + x = ux.f; + if (sy) + y = -y; + if (ex == ey || (ex+1 == ey && (2*x > y || (2*x == y && q%2)))) { + x -= y; + q++; + } q &= 0x7fffffff; - *quo = sxy ? -q : q; - return x; + *quo = sx^sy ? -(int)q : (int)q; + return sx ? -x : x; } #endif diff -Nur musl-0.9.13/src/math/rint.c musl-git/src/math/rint.c --- musl-0.9.13/src/math/rint.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/rint.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,90 +1,20 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_rint.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * rint(x) - * Return x rounded to integral value according to the prevailing - * rounding mode. - * Method: - * Using floating addition. - * Exception: - * Inexact flag raised if x not equal to rint(x). - */ - -#include "libm.h" - -static const double -TWO52[2] = { - 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ -}; +#include +#include double rint(double x) { - int32_t i0,j0,sx; - uint32_t i,i1; - double w,t; + union {double f; uint64_t i;} u = {x}; + int e = u.i>>52 & 0x7ff; + int s = u.i>>63; + double_t y; - EXTRACT_WORDS(i0, i1, x); - // FIXME: signed shift - sx = (i0>>31) & 1; - j0 = ((i0>>20)&0x7ff) - 0x3ff; - if (j0 < 20) { - if (j0 < 0) { - if (((i0&0x7fffffff)|i1) == 0) - return x; - i1 |= i0 & 0x0fffff; - i0 &= 0xfffe0000; - i0 |= ((i1|-i1)>>12) & 0x80000; - SET_HIGH_WORD(x, i0); - STRICT_ASSIGN(double, w, TWO52[sx] + x); - t = w - TWO52[sx]; - GET_HIGH_WORD(i0, t); - SET_HIGH_WORD(t, (i0&0x7fffffff)|(sx<<31)); - return t; - } else { - i = 0x000fffff>>j0; - if (((i0&i)|i1) == 0) - return x; /* x is integral */ - i >>= 1; - if (((i0&i)|i1) != 0) { - /* - * Some bit is set after the 0.5 bit. To avoid the - * possibility of errors from double rounding in - * w = TWO52[sx]+x, adjust the 0.25 bit to a lower - * guard bit. We do this for all j0<=51. The - * adjustment is trickiest for j0==18 and j0==19 - * since then it spans the word boundary. - */ - if (j0 == 19) - i1 = 0x40000000; - else if (j0 == 18) - i1 = 0x80000000; - else - i0 = (i0 & ~i)|(0x20000>>j0); - } - } - } else if (j0 > 51) { - if (j0 == 0x400) - return x+x; /* inf or NaN */ - return x; /* x is integral */ - } else { - i = (uint32_t)0xffffffff>>(j0-20); - if ((i1&i) == 0) - return x; /* x is integral */ - i >>= 1; - if ((i1&i) != 0) - i1 = (i1 & ~i)|(0x40000000>>(j0-20)); - } - INSERT_WORDS(x, i0, i1); - STRICT_ASSIGN(double, w, TWO52[sx] + x); - return w - TWO52[sx]; + if (e >= 0x3ff+52) + return x; + if (s) + y = (double)(x - 0x1p52) + 0x1p52; + else + y = (double)(x + 0x1p52) - 0x1p52; + if (y == 0) + return s ? -0.0 : 0; + return y; } diff -Nur musl-0.9.13/src/math/rintf.c musl-git/src/math/rintf.c --- musl-0.9.13/src/math/rintf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/rintf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,48 +1,20 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_rintf.c */ -/* - * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. - */ -/* - * ==================================================== - * 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 "libm.h" - -static const float -TWO23[2] = { - 8.3886080000e+06, /* 0x4b000000 */ - -8.3886080000e+06, /* 0xcb000000 */ -}; +#include +#include float rintf(float x) { - int32_t i0,j0,sx; - float w,t; + union {float f; uint32_t i;} u = {x}; + int e = u.i>>23 & 0xff; + int s = u.i>>31; + float_t y; - GET_FLOAT_WORD(i0, x); - sx = (i0>>31) & 1; - j0 = ((i0>>23)&0xff) - 0x7f; - if (j0 < 23) { - if (j0 < 0) { - if ((i0&0x7fffffff) == 0) - return x; - STRICT_ASSIGN(float, w, TWO23[sx] + x); - t = w - TWO23[sx]; - GET_FLOAT_WORD(i0, t); - SET_FLOAT_WORD(t, (i0&0x7fffffff)|(sx<<31)); - return t; - } - STRICT_ASSIGN(float, w, TWO23[sx] + x); - return w - TWO23[sx]; - } - if (j0 == 0x80) - return x+x; /* inf or NaN */ - return x; /* x is integral */ + if (e >= 0x7f+23) + return x; + if (s) + y = (float)(x - 0x1p23f) + 0x1p23f; + else + y = (float)(x + 0x1p23f) - 0x1p23f; + if (y == 0) + return s ? -0.0f : 0.0f; + return y; } diff -Nur musl-0.9.13/src/math/rintl.c musl-git/src/math/rintl.c --- musl-0.9.13/src/math/rintl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/rintl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,30 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_rintl.c */ -/*- - * Copyright (c) 2008 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -33,53 +6,26 @@ return rint(x); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 - -#define BIAS (LDBL_MAX_EXP - 1) - -static const float -shift[2] = { #if LDBL_MANT_DIG == 64 - 0x1.0p63, -0x1.0p63 +#define TOINT 0x1p63 #elif LDBL_MANT_DIG == 113 - 0x1.0p112, -0x1.0p112 +#define TOINT 0x1p112 #endif -}; -static const float zero[2] = { 0.0, -0.0 }; - long double rintl(long double x) { - union IEEEl2bits u; - uint32_t expsign; - int ex, sign; - - u.e = x; - expsign = u.xbits.expsign; - ex = expsign & 0x7fff; - - if (ex >= BIAS + LDBL_MANT_DIG - 1) { - if (ex == BIAS + LDBL_MAX_EXP) - return x + x; /* Inf, NaN, or unsupported format */ - return x; /* finite and already an integer */ - } - sign = expsign >> 15; - - /* - * The following code assumes that intermediate results are - * evaluated in long double precision. If they are evaluated in - * greater precision, double rounding may occur, and if they are - * evaluated in less precision (as on i386), results will be - * wildly incorrect. - */ - x += shift[sign]; - x -= shift[sign]; - - /* - * If the result is +-0, then it must have the same sign as x, but - * the above calculation doesn't always give this. Fix up the sign. - */ - if (ex < BIAS && x == 0.0) - return zero[sign]; - - return x; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + int s = u.i.se >> 15; + long double y; + + if (e >= 0x3fff+LDBL_MANT_DIG-1) + return x; + if (s) + y = x - TOINT + TOINT; + else + y = x + TOINT - TOINT; + if (y == 0) + return 0*x; + return y; } #endif diff -Nur musl-0.9.13/src/math/round.c musl-git/src/math/round.c --- musl-0.9.13/src/math/round.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/round.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,48 +1,28 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_round.c */ -/*- - * Copyright (c) 2003, Steven G. Kargl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include +#include "libm.h" double round(double x) { - double t; + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double_t y; - if (!isfinite(x)) + if (e >= 0x3ff+52) return x; - - if (x >= 0.0) { - t = floor(x); - if (t - x <= -0.5) - t += 1.0; - return t; - } else { - t = floor(-x); - if (t + x <= -0.5) - t += 1.0; - return -t; + if (u.i >> 63) + x = -x; + if (e < 0x3ff-1) { + /* raise inexact if x!=0 */ + FORCE_EVAL(x + 0x1p52); + return 0*u.f; } + y = (double)(x + 0x1p52) - 0x1p52 - x; + if (y > 0.5) + y = y + x - 1; + else if (y <= -0.5) + y = y + x + 1; + else + y = y + x; + if (u.i >> 63) + y = -y; + return y; } diff -Nur musl-0.9.13/src/math/roundf.c musl-git/src/math/roundf.c --- musl-0.9.13/src/math/roundf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/roundf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,48 +1,27 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_roundf.c */ -/*- - * Copyright (c) 2003, Steven G. Kargl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include +#include "libm.h" float roundf(float x) { - float t; + union {float f; uint32_t i;} u = {x}; + int e = u.i >> 23 & 0xff; + float_t y; - if (!isfinite(x)) + if (e >= 0x7f+23) return x; - - if (x >= 0.0) { - t = floorf(x); - if (t - x <= -0.5) - t += 1.0; - return t; - } else { - t = floorf(-x); - if (t + x <= -0.5) - t += 1.0; - return -t; + if (u.i >> 31) + x = -x; + if (e < 0x7f-1) { + FORCE_EVAL(x + 0x1p23f); + return 0*u.f; } + y = (float)(x + 0x1p23f) - 0x1p23f - x; + if (y > 0.5f) + y = y + x - 1; + else if (y <= -0.5f) + y = y + x + 1; + else + y = y + x; + if (u.i >> 31) + y = -y; + return y; } diff -Nur musl-0.9.13/src/math/roundl.c musl-git/src/math/roundl.c --- musl-0.9.13/src/math/roundl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/roundl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,56 +1,39 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_roundl.c */ -/*- - * Copyright (c) 2003, Steven G. Kargl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include +#include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 long double roundl(long double x) { return round(x); } -#else +#elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 +#if LDBL_MANT_DIG == 64 +#define TOINT 0x1p63 +#elif LDBL_MANT_DIG == 113 +#define TOINT 0x1p112 +#endif long double roundl(long double x) { - long double t; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + long double y; - if (!isfinite(x)) + if (e >= 0x3fff+LDBL_MANT_DIG-1) return x; - - if (x >= 0.0) { - t = floorl(x); - if (t - x <= -0.5) - t += 1.0; - return t; - } else { - t = floorl(-x); - if (t + x <= -0.5) - t += 1.0; - return -t; + if (u.i.se >> 15) + x = -x; + if (e < 0x3fff-1) { + FORCE_EVAL(x + TOINT); + return 0*u.f; } + y = x + TOINT - TOINT - x; + if (y > 0.5) + y = y + x - 1; + else if (y <= -0.5) + y = y + x + 1; + else + y = y + x; + if (u.i.se >> 15) + y = -y; + return y; } #endif diff -Nur musl-0.9.13/src/math/scalbn.c musl-git/src/math/scalbn.c --- musl-0.9.13/src/math/scalbn.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/scalbn.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,29 +1,31 @@ -#include "libm.h" +#include +#include double scalbn(double x, int n) { - double scale; + union {double f; uint64_t i;} u; + double_t y = x; if (n > 1023) { - x *= 0x1p1023; + y *= 0x1p1023; n -= 1023; if (n > 1023) { - x *= 0x1p1023; + y *= 0x1p1023; n -= 1023; if (n > 1023) n = 1023; } } else if (n < -1022) { - x *= 0x1p-1022; + y *= 0x1p-1022; n += 1022; if (n < -1022) { - x *= 0x1p-1022; + y *= 0x1p-1022; n += 1022; if (n < -1022) n = -1022; } } - INSERT_WORDS(scale, (uint32_t)(0x3ff+n)<<20, 0); - STRICT_ASSIGN(double, x, x * scale); + u.i = (uint64_t)(0x3ff+n)<<52; + x = y * u.f; return x; } diff -Nur musl-0.9.13/src/math/scalbnf.c musl-git/src/math/scalbnf.c --- musl-0.9.13/src/math/scalbnf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/scalbnf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,29 +1,31 @@ -#include "libm.h" +#include +#include float scalbnf(float x, int n) { - float scale; + union {float f; uint32_t i;} u; + float_t y = x; if (n > 127) { - x *= 0x1p127f; + y *= 0x1p127f; n -= 127; if (n > 127) { - x *= 0x1p127f; + y *= 0x1p127f; n -= 127; if (n > 127) n = 127; } } else if (n < -126) { - x *= 0x1p-126f; + y *= 0x1p-126f; n += 126; if (n < -126) { - x *= 0x1p-126f; + y *= 0x1p-126f; n += 126; if (n < -126) n = -126; } } - SET_FLOAT_WORD(scale, (uint32_t)(0x7f+n)<<23); - STRICT_ASSIGN(float, x, x * scale); + u.i = (uint32_t)(0x7f+n)<<23; + x = y * u.f; return x; } diff -Nur musl-0.9.13/src/math/scalbnl.c musl-git/src/math/scalbnl.c --- musl-0.9.13/src/math/scalbnl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/scalbnl.c 2013-09-16 20:31:39.000000000 +0200 @@ -8,7 +8,7 @@ #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 long double scalbnl(long double x, int n) { - union IEEEl2bits scale; + union ldshape u; if (n > 16383) { x *= 0x1p16383L; @@ -29,8 +29,8 @@ n = -16382; } } - scale.e = 1.0; - scale.bits.exp = 0x3fff + n; - return x * scale.e; + u.f = 1.0; + u.i.se = 0x3fff + n; + return x * u.f; } #endif diff -Nur musl-0.9.13/src/math/signgam.c musl-git/src/math/signgam.c --- musl-0.9.13/src/math/signgam.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/signgam.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,4 +1,5 @@ -#include "libm.h" +#include +#include "libc.h" int __signgam = 0; diff -Nur musl-0.9.13/src/math/sincosl.c musl-git/src/math/sincosl.c --- musl-0.9.13/src/math/sincosl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/sincosl.c 2013-09-16 20:31:39.000000000 +0200 @@ -9,25 +9,19 @@ #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 void sincosl(long double x, long double *sin, long double *cos) { - union IEEEl2bits u; + union ldshape u = {x}; unsigned n; long double y[2], s, c; - u.e = x; - u.bits.sign = 0; - - /* x = nan or inf */ - if (u.bits.exp == 0x7fff) { + u.i.se &= 0x7fff; + if (u.i.se == 0x7fff) { *sin = *cos = x - x; return; } - - /* |x| < (double)pi/4 */ - if (u.e < M_PI_4) { - /* |x| < 0x1p-64 */ - if (u.bits.exp < 0x3fff - 64) { + if (u.f < M_PI_4) { + if (u.i.se < 0x3fff - LDBL_MANT_DIG) { /* raise underflow if subnormal */ - if (u.bits.exp == 0) FORCE_EVAL(x*0x1p-120f); + if (u.i.se == 0) FORCE_EVAL(x*0x1p-120f); *sin = x; /* raise inexact if x!=0 */ *cos = 1.0 + x; @@ -37,7 +31,6 @@ *cos = __cosl(x, 0); return; } - n = __rem_pio2l(x, y); s = __sinl(y[0], y[1], 1); c = __cosl(y[0], y[1]); diff -Nur musl-0.9.13/src/math/sinhl.c musl-git/src/math/sinhl.c --- musl-0.9.13/src/math/sinhl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/sinhl.c 2013-09-16 20:31:39.000000000 +0200 @@ -8,10 +8,7 @@ #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 long double sinhl(long double x) { - union { - long double f; - struct{uint64_t m; uint16_t se; uint16_t pad;} i; - } u = {.f = x}; + union ldshape u = {x}; unsigned ex = u.i.se & 0x7fff; long double h, t, absx; diff -Nur musl-0.9.13/src/math/sinl.c musl-git/src/math/sinl.c --- musl-0.9.13/src/math/sinl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/sinl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,31 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_sinl.c */ -/*- - * Copyright (c) 2007 Steven G. Kargl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -36,46 +8,34 @@ #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 long double sinl(long double x) { - union IEEEl2bits z; + union ldshape u = {x}; unsigned n; - long double y[2]; - long double hi, lo; - - z.e = x; - z.bits.sign = 0; + long double y[2], hi, lo; - /* If x = NaN or Inf, then sin(x) = NaN. */ - if (z.bits.exp == 0x7fff) - return (x - x) / (x - x); - - /* |x| < (double)pi/4 */ - if (z.e < M_PI_4) { - /* |x| < 0x1p-64 */ - if (z.bits.exp < 0x3fff - 64) { + u.i.se &= 0x7fff; + if (u.i.se == 0x7fff) + return x - x; + if (u.f < M_PI_4) { + if (u.i.se < 0x3fff - LDBL_MANT_DIG/2) { /* raise inexact if x!=0 and underflow if subnormal */ - FORCE_EVAL(z.bits.exp == 0 ? x/0x1p120f : x+0x1p120f); + FORCE_EVAL(u.i.se == 0 ? x*0x1p-120f : x+0x1p120f); return x; } return __sinl(x, 0.0, 0); } - n = __rem_pio2l(x, y); hi = y[0]; lo = y[1]; switch (n & 3) { case 0: - hi = __sinl(hi, lo, 1); - break; + return __sinl(hi, lo, 1); case 1: - hi = __cosl(hi, lo); - break; + return __cosl(hi, lo); case 2: - hi = -__sinl(hi, lo, 1); - break; + return -__sinl(hi, lo, 1); case 3: - hi = -__cosl(hi, lo); - break; + default: + return -__cosl(hi, lo); } - return hi; } #endif diff -Nur musl-0.9.13/src/math/sqrtl.c musl-git/src/math/sqrtl.c --- musl-0.9.13/src/math/sqrtl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/sqrtl.c 2013-09-16 20:31:39.000000000 +0200 @@ -2,8 +2,6 @@ long double sqrtl(long double x) { - /* FIXME: implement sqrtl in C. At least this works for now on - * ARM (which uses ld64), the only arch without sqrtl asm - * that's supported so far. */ + /* FIXME: implement in C, this is for LDBL_MANT_DIG == 64 only */ return sqrt(x); } diff -Nur musl-0.9.13/src/math/tanhl.c musl-git/src/math/tanhl.c --- musl-0.9.13/src/math/tanhl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/tanhl.c 2013-09-16 20:31:39.000000000 +0200 @@ -8,10 +8,7 @@ #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 long double tanhl(long double x) { - union { - long double f; - struct{uint64_t m; uint16_t se; uint16_t pad;} i; - } u = {.f = x}; + union ldshape u = {x}; unsigned ex = u.i.se & 0x7fff; unsigned sign = u.i.se & 0x8000; uint32_t w; diff -Nur musl-0.9.13/src/math/tanl.c musl-git/src/math/tanl.c --- musl-0.9.13/src/math/tanl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/tanl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,35 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_tanl.c */ -/*- - * Copyright (c) 2007 Steven G. Kargl - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * Limited testing on pseudorandom numbers drawn within [0:4e8] shows - * an accuracy of <= 1.5 ULP where 247024 values of x out of 40 million - * possibles resulted in tan(x) that exceeded 0.5 ULP (ie., 0.6%). - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -40,28 +8,21 @@ #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 long double tanl(long double x) { - union IEEEl2bits z; + union ldshape u = {x}; long double y[2]; unsigned n; - z.e = x; - z.bits.sign = 0; - - /* If x = NaN or Inf, then tan(x) = NaN. */ - if (z.bits.exp == 0x7fff) - return (x - x) / (x - x); - - /* |x| < (double)pi/4 */ - if (z.e < M_PI_4) { - /* |x| < 0x1p-64 */ - if (z.bits.exp < 0x3fff - 64) { + u.i.se &= 0x7fff; + if (u.i.se == 0x7fff) + return x - x; + if (u.f < M_PI_4) { + if (u.i.se < 0x3fff - LDBL_MANT_DIG/2) { /* raise inexact if x!=0 and underflow if subnormal */ - FORCE_EVAL(z.bits.exp == 0 ? x/0x1p120f : x+0x1p120f); + FORCE_EVAL(u.i.se == 0 ? x*0x1p-120f : x+0x1p120f); return x; } return __tanl(x, 0, 0); } - n = __rem_pio2l(x, y); return __tanl(y[0], y[1], n&1); } diff -Nur musl-0.9.13/src/math/trunc.c musl-git/src/math/trunc.c --- musl-0.9.13/src/math/trunc.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/trunc.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,63 +1,19 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_trunc.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * trunc(x) - * Return x rounded toward 0 to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to trunc(x). - */ - #include "libm.h" -static const double huge = 1.0e300; - double trunc(double x) { - int32_t i0,i1,j0; - uint32_t i; + union {double f; uint64_t i;} u = {x}; + int e = (int)(u.i >> 52 & 0x7ff) - 0x3ff + 12; + uint64_t m; - EXTRACT_WORDS(i0, i1, x); - j0 = ((i0>>20)&0x7ff) - 0x3ff; - if (j0 < 20) { - if (j0 < 0) { /* |x|<1, return 0*sign(x) */ - /* raise inexact if x != 0 */ - if (huge+x > 0.0) { - i0 &= 0x80000000U; - i1 = 0; - } - } else { - i = 0x000fffff>>j0; - if (((i0&i)|i1) == 0) - return x; /* x is integral */ - /* raise inexact */ - if (huge+x > 0.0) { - i0 &= ~i; - i1 = 0; - } - } - } else if (j0 > 51) { - if (j0 == 0x400) - return x + x; /* inf or NaN */ - return x; /* x is integral */ - } else { - i = (uint32_t)0xffffffff>>(j0-20); - if ((i1&i) == 0) - return x; /* x is integral */ - /* raise inexact */ - if (huge+x > 0.0) - i1 &= ~i; - } - INSERT_WORDS(x, i0, i1); - return x; + if (e >= 52 + 12) + return x; + if (e < 12) + e = 1; + m = -1ULL >> e; + if ((u.i & m) == 0) + return x; + FORCE_EVAL(x + 0x1p120f); + u.i &= ~m; + return u.f; } diff -Nur musl-0.9.13/src/math/truncf.c musl-git/src/math/truncf.c --- musl-0.9.13/src/math/truncf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/truncf.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,52 +1,19 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_truncf.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * truncf(x) - * Return x rounded toward 0 to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to truncf(x). - */ - #include "libm.h" -static const float huge = 1.0e30f; - float truncf(float x) { - int32_t i0,j0; - uint32_t i; + union {float f; uint32_t i;} u = {x}; + int e = (int)(u.i >> 23 & 0xff) - 0x7f + 9; + uint32_t m; - GET_FLOAT_WORD(i0, x); - j0 = ((i0>>23)&0xff) - 0x7f; - if (j0 < 23) { - if (j0 < 0) { /* |x|<1, return 0*sign(x) */ - /* raise inexact if x != 0 */ - if (huge+x > 0.0f) - i0 &= 0x80000000; - } else { - i = 0x007fffff>>j0; - if ((i0&i) == 0) - return x; /* x is integral */ - /* raise inexact */ - if (huge+x > 0.0f) - i0 &= ~i; - } - } else { - if (j0 == 0x80) - return x + x; /* inf or NaN */ - return x; /* x is integral */ - } - SET_FLOAT_WORD(x, i0); - return x; + if (e >= 23 + 9) + return x; + if (e < 9) + e = 1; + m = -1U >> e; + if ((u.i & m) == 0) + return x; + FORCE_EVAL(x + 0x1p120f); + u.i &= ~m; + return u.f; } diff -Nur musl-0.9.13/src/math/truncl.c musl-git/src/math/truncl.c --- musl-0.9.13/src/math/truncl.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/truncl.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,23 +1,3 @@ -/* origin: FreeBSD /usr/src/lib/msun/src/s_truncl.c */ -/* - * ==================================================== - * 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. - * ==================================================== - */ -/* - * truncl(x) - * Return x rounded toward 0 to integral value - * Method: - * Bit twiddling. - * Exception: - * Inexact flag raised if x not equal to truncl(x). - */ - #include "libm.h" #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -26,43 +6,31 @@ return trunc(x); } #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384 -#ifdef LDBL_IMPLICIT_NBIT -#define MANH_SIZE (LDBL_MANH_SIZE + 1) -#else -#define MANH_SIZE LDBL_MANH_SIZE +#if LDBL_MANT_DIG == 64 +#define TOINT 0x1p63 +#elif LDBL_MANT_DIG == 113 +#define TOINT 0x1p112 #endif - -static const long double huge = 1.0e300; -static const float zero[] = { 0.0, -0.0 }; - long double truncl(long double x) { - union IEEEl2bits u = { .e = x }; - int e = u.bits.exp - LDBL_MAX_EXP + 1; + union ldshape u = {x}; + int e = u.i.se & 0x7fff; + int s = u.i.se >> 15; + long double y; - if (e < MANH_SIZE - 1) { - if (e < 0) { - /* raise inexact if x != 0 */ - if (huge + x > 0.0) - u.e = zero[u.bits.sign]; - } else { - uint64_t m = ((1llu << MANH_SIZE) - 1) >> (e + 1); - if (((u.bits.manh & m) | u.bits.manl) == 0) - return x; /* x is integral */ - /* raise inexact */ - if (huge + x > 0.0) { - u.bits.manh &= ~m; - u.bits.manl = 0; - } - } - } else if (e < LDBL_MANT_DIG - 1) { - uint64_t m = (uint64_t)-1 >> (64 - LDBL_MANT_DIG + e + 1); - if ((u.bits.manl & m) == 0) - return x; /* x is integral */ - /* raise inexact */ - if (huge + x > 0.0) - u.bits.manl &= ~m; + if (e >= 0x3fff+LDBL_MANT_DIG-1) + return x; + if (e <= 0x3fff-1) { + FORCE_EVAL(x + 0x1p120f); + return x*0; } - return u.e; + /* y = int(|x|) - |x|, where int(|x|) is an integer neighbor of |x| */ + if (s) + x = -x; + y = x + TOINT - TOINT - x; + if (y > 0) + y -= 1; + x += y; + return s ? -x : x; } #endif diff -Nur musl-0.9.13/src/math/x86_64/ceill.s musl-git/src/math/x86_64/ceill.s --- musl-0.9.13/src/math/x86_64/ceill.s 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/x86_64/ceill.s 2013-09-16 20:31:39.000000000 +0200 @@ -1 +1 @@ -# see floor.s +# see floorl.s diff -Nur musl-0.9.13/src/math/x86_64/exp2l.s musl-git/src/math/x86_64/exp2l.s --- musl-0.9.13/src/math/x86_64/exp2l.s 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/x86_64/exp2l.s 2013-09-16 20:31:39.000000000 +0200 @@ -4,8 +4,18 @@ fldt 8(%rsp) fldl2e fmulp + movl $0xc2820000,-4(%rsp) + flds -4(%rsp) + fucomp %st(1) + fnstsw %ax + sahf fld1 - fld %st(1) + jb 1f + # x*log2e <= -65, return -1 without underflow + fstp %st(1) + fchs + ret +1: fld %st(1) fabs fucom %st(1) fnstsw %ax @@ -26,44 +36,32 @@ .type exp2l,@function exp2l: fldt 8(%rsp) -1: mov $0x467ff000,%eax - mov %eax,-16(%rsp) - mov $0x80000000,%eax - mov %eax,-20(%rsp) - xor %eax,%eax - mov %eax,-24(%rsp) - flds -16(%rsp) # 16380 +1: fld %st(0) + sub $16,%rsp + fstpt (%rsp) + mov 8(%rsp),%ax + and $0x7fff,%ax + cmp $0x3fff+13,%ax + jb 4f # |x| < 8192 + cmp $0x3fff+15,%ax + jae 3f # |x| >= 32768 + fsts (%rsp) + cmpl $0xc67ff800,(%rsp) + jb 2f # x > -16382 + movl $0x5f000000,(%rsp) + flds (%rsp) # 0x1p63 fld %st(1) - fabs - fucom %st(1) + fsub %st(1) + faddp + fucomp %st(1) fnstsw - fstp %st(0) - fstp %st(0) sahf - ja 3f # |x| > 16380 - jp 2f # x is nan (avoid invalid except in fistp) - fld %st(0) - fistpl -16(%rsp) - fildl -16(%rsp) - fxch %st(1) - fsub %st(1) - mov $0x3fff,%eax - add %eax,-16(%rsp) - f2xm1 - fld1 - faddp # 2^(x-rint(x)) - fldt -24(%rsp) # 2^rint(x) - fmulp -2: fstp %st(1) - ret - -3: fld %st(0) - fstpt -24(%rsp) - fld1 - mov -15(%rsp),%ax - and $0x7fff,%ax - cmp $0x7fff,%ax - je 1f # x = +-inf + je 2f # x - 0x1p63 + 0x1p63 == x + movl $1,(%rsp) + flds (%rsp) # 0x1p-149 + fdiv %st(1) + fstps (%rsp) # raise underflow +2: fld1 fld %st(1) frndint fxch %st(2) @@ -72,4 +70,21 @@ faddp # 2^(x-rint(x)) 1: fscale fstp %st(1) + add $16,%rsp + ret +3: xor %eax,%eax +4: cmp $0x3fff-64,%ax + fld1 + jb 1b # |x| < 0x1p-64 + fstpt (%rsp) + fistl 8(%rsp) + fildl 8(%rsp) + fsubrp %st(1) + addl $0x3fff,8(%rsp) + f2xm1 + fld1 + faddp # 2^(x-rint(x)) + fldt (%rsp) # 2^rint(x) + fmulp + add $16,%rsp ret diff -Nur musl-0.9.13/src/math/x86_64/lrintl.s musl-git/src/math/x86_64/lrintl.s --- musl-0.9.13/src/math/x86_64/lrintl.s 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/x86_64/lrintl.s 2013-09-16 20:31:39.000000000 +0200 @@ -2,6 +2,6 @@ .type lrintl,@function lrintl: fldt 8(%rsp) - fistpl 8(%rsp) - mov 8(%rsp),%eax + fistpll 8(%rsp) + mov 8(%rsp),%rax ret diff -Nur musl-0.9.13/src/math/x86_64/truncl.s musl-git/src/math/x86_64/truncl.s --- musl-0.9.13/src/math/x86_64/truncl.s 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/math/x86_64/truncl.s 2013-09-16 20:31:39.000000000 +0200 @@ -1 +1 @@ -# see floor.s +# see floorl.s diff -Nur musl-0.9.13/src/misc/realpath.c musl-git/src/misc/realpath.c --- musl-0.9.13/src/misc/realpath.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/misc/realpath.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,10 +1,11 @@ #include -#include #include #include #include #include #include +#include +#include "syscall.h" void __procfdname(char *, unsigned); @@ -14,38 +15,31 @@ ssize_t r; struct stat st1, st2; char buf[15+3*sizeof(int)]; - int alloc = 0; + char tmp[PATH_MAX]; if (!filename) { errno = EINVAL; return 0; } - fd = open(filename, O_RDONLY|O_NONBLOCK|O_CLOEXEC); + fd = syscall(SYS_open, filename, O_PATH|O_NONBLOCK|O_CLOEXEC|O_LARGEFILE); if (fd < 0) return 0; __procfdname(buf, fd); - if (!resolved) { - alloc = 1; - resolved = malloc(PATH_MAX); - if (!resolved) return 0; - } - - r = readlink(buf, resolved, PATH_MAX-1); + r = readlink(buf, tmp, sizeof tmp - 1); if (r < 0) goto err; - resolved[r] = 0; + tmp[r] = 0; fstat(fd, &st1); - r = stat(resolved, &st2); + r = stat(tmp, &st2); if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { if (!r) errno = ELOOP; goto err; } - close(fd); - return resolved; + __syscall(SYS_close, fd); + return resolved ? strcpy(resolved, tmp) : strdup(tmp); err: - if (alloc) free(resolved); - close(fd); + __syscall(SYS_close, fd); return 0; } diff -Nur musl-0.9.13/src/mman/mprotect.c musl-git/src/mman/mprotect.c --- musl-0.9.13/src/mman/mprotect.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/mman/mprotect.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,5 +1,5 @@ #include -#include +#include "libc.h" #include "syscall.h" int mprotect(void *addr, size_t len, int prot) diff -Nur musl-0.9.13/src/signal/sigemptyset.c musl-git/src/signal/sigemptyset.c --- musl-0.9.13/src/signal/sigemptyset.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/signal/sigemptyset.c 2013-09-16 20:31:39.000000000 +0200 @@ -4,6 +4,10 @@ int sigemptyset(sigset_t *set) { set->__bits[0] = 0; - if (sizeof(long)==4) set->__bits[1] = 0; + if (sizeof(long)==4 || _NSIG > 65) set->__bits[1] = 0; + if (sizeof(long)==4 && _NSIG > 65) { + set->__bits[2] = 0; + set->__bits[3] = 0; + } return 0; } diff -Nur musl-0.9.13/src/signal/sigfillset.c musl-git/src/signal/sigfillset.c --- musl-0.9.13/src/signal/sigfillset.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/signal/sigfillset.c 2013-09-16 20:31:39.000000000 +0200 @@ -7,8 +7,13 @@ #if ULONG_MAX == 0xffffffff set->__bits[0] = 0x7ffffffful; set->__bits[1] = 0xfffffffcul; + if (_NSIG > 65) { + set->__bits[2] = 0xfffffffful; + set->__bits[3] = 0xfffffffful; + } #else set->__bits[0] = 0xfffffffc7ffffffful; + if (_NSIG > 65) set->__bits[1] = 0xfffffffffffffffful; #endif return 0; } diff -Nur musl-0.9.13/src/signal/sigqueue.c musl-git/src/signal/sigqueue.c --- musl-0.9.13/src/signal/sigqueue.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/signal/sigqueue.c 2013-09-16 20:31:39.000000000 +0200 @@ -3,6 +3,7 @@ #include #include #include "syscall.h" +#include "pthread_impl.h" int sigqueue(pid_t pid, int sig, const union sigval value) { @@ -14,9 +15,9 @@ si.si_code = SI_QUEUE; si.si_value = value; si.si_uid = getuid(); - pthread_sigmask(SIG_BLOCK, (void *)(uint64_t[1]){-1}, &set); + __block_app_sigs(&set); si.si_pid = getpid(); r = syscall(SYS_rt_sigqueueinfo, pid, sig, &si); - pthread_sigmask(SIG_SETMASK, &set, 0); + __restore_sigs(&set); return r; } diff -Nur musl-0.9.13/src/stdio/popen.c musl-git/src/stdio/popen.c --- musl-0.9.13/src/stdio/popen.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/stdio/popen.c 2013-09-16 20:31:39.000000000 +0200 @@ -39,7 +39,7 @@ * remove the close-on-exec flag in the child without also creating * a file descriptor leak race condition in the parent. */ if (p[1-op] == 1-op) { - int tmp = fcntl(F_DUPFD_CLOEXEC, 1-op, 0); + int tmp = fcntl(1-op, F_DUPFD_CLOEXEC, 0); if (tmp < 0) { e = errno; goto fail; diff -Nur musl-0.9.13/src/stdio/vfscanf.c musl-git/src/stdio/vfscanf.c --- musl-0.9.13/src/stdio/vfscanf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/stdio/vfscanf.c 2013-09-16 20:31:39.000000000 +0200 @@ -118,6 +118,8 @@ } if (*p=='m') { + wcs = 0; + s = 0; alloc = !!dest; p++; } else { diff -Nur musl-0.9.13/src/stdio/vfwscanf.c musl-git/src/stdio/vfwscanf.c --- musl-0.9.13/src/stdio/vfwscanf.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/stdio/vfwscanf.c 2013-09-16 20:31:39.000000000 +0200 @@ -143,6 +143,8 @@ } if (*p=='m') { + wcs = 0; + s = 0; alloc = !!dest; p++; } else { diff -Nur musl-0.9.13/src/temp/__randname.c musl-git/src/temp/__randname.c --- musl-0.9.13/src/temp/__randname.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/temp/__randname.c 2013-09-16 20:31:39.000000000 +0200 @@ -5,7 +5,7 @@ int __clock_gettime(clockid_t, struct timespec *); /* This assumes that a check for the - template size has alrady been made */ + template size has already been made */ char *__randname(char *template) { int i; diff -Nur musl-0.9.13/src/thread/mips/clone.s musl-git/src/thread/mips/clone.s --- musl-0.9.13/src/thread/mips/clone.s 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/thread/mips/clone.s 2013-09-16 20:31:39.000000000 +0200 @@ -3,6 +3,7 @@ .type __clone,@function __clone: # Save function pointer and argument pointer on new thread stack + and $5, $5, -8 subu $5, $5, 16 sw $4, 0($5) sw $7, 4($5) @@ -11,15 +12,18 @@ lw $6, 16($sp) lw $7, 20($sp) lw $9, 24($sp) + subu $sp, $sp, 16 sw $9, 16($sp) li $2, 4120 syscall beq $7, $0, 1f nop + addu $sp, $sp, 16 jr $ra subu $2, $0, $2 1: beq $2, $0, 1f nop + addu $sp, $sp, 16 jr $ra nop 1: lw $25, 0($sp) diff -Nur musl-0.9.13/src/thread/pthread_create.c musl-git/src/thread/pthread_create.c --- musl-0.9.13/src/thread/pthread_create.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/thread/pthread_create.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,5 +1,7 @@ +#define _GNU_SOURCE #include "pthread_impl.h" #include "stdio_impl.h" +#include "libc.h" #include static void dummy_0() @@ -127,7 +129,9 @@ size_t size, guard; struct pthread *self = pthread_self(), *new; unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit; - unsigned flags = 0x7d8f00; + unsigned flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND + | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS + | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_DETACHED; int do_sched = 0; pthread_attr_t attr = {0}; @@ -197,7 +201,7 @@ new->tsd = (void *)tsd; if (attr._a_detach) { new->detached = 1; - flags -= 0x200000; + flags -= CLONE_CHILD_CLEARTID; } if (attr._a_sched) { do_sched = new->startlock[0] = 1; diff -Nur musl-0.9.13/src/thread/pthread_getattr_np.c musl-git/src/thread/pthread_getattr_np.c --- musl-0.9.13/src/thread/pthread_getattr_np.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/thread/pthread_getattr_np.c 2013-09-16 20:31:39.000000000 +0200 @@ -1,5 +1,6 @@ #define _GNU_SOURCE #include "pthread_impl.h" +#include "libc.h" #include int pthread_getattr_np(pthread_t t, pthread_attr_t *a) diff -Nur musl-0.9.13/src/thread/synccall.c musl-git/src/thread/synccall.c --- musl-0.9.13/src/thread/synccall.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/thread/synccall.c 2013-09-16 20:31:39.000000000 +0200 @@ -43,7 +43,7 @@ pthread_t self; struct sigaction sa; struct chain *next; - uint64_t oldmask; + sigset_t oldmask; if (!libc.threads_minus_1) { func(ctx); @@ -52,12 +52,12 @@ __inhibit_ptc(); - __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGALL_SET, - &oldmask, _NSIG/8); + __block_all_sigs(&oldmask); sem_init(&chaindone, 0, 0); sem_init(&chainlock, 0, 1); chainlen = 0; + head = 0; callback = func; context = ctx; @@ -70,6 +70,10 @@ sigqueue(self->pid, SIGSYNCCALL, (union sigval){0}); while (sem_wait(&chaindone)); + sa.sa_flags = 0; + sa.sa_handler = SIG_IGN; + __libc_sigaction(SIGSYNCCALL, &sa, 0); + for (cur=head; cur; cur=cur->next) { sem_post(&cur->sem); while (sem_wait(&cur->sem2)); @@ -81,12 +85,7 @@ sem_post(&cur->sem); } - sa.sa_flags = 0; - sa.sa_handler = SIG_IGN; - __libc_sigaction(SIGSYNCCALL, &sa, 0); - - __syscall(SYS_rt_sigprocmask, SIG_SETMASK, - &oldmask, 0, _NSIG/8); + __restore_sigs(&oldmask); __release_ptc(); } diff -Nur musl-0.9.13/src/unistd/faccessat.c musl-git/src/unistd/faccessat.c --- musl-0.9.13/src/unistd/faccessat.c 2013-08-30 23:30:53.000000000 +0200 +++ musl-git/src/unistd/faccessat.c 2013-09-16 20:31:39.000000000 +0200 @@ -19,7 +19,7 @@ __syscall(SYS_exit, 1); ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0); __syscall(SYS_write, c->p, &ret, sizeof ret); - __syscall(SYS_exit, 0); + return 0; } int faccessat(int fd, const char *filename, int amode, int flag)