diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index d366cf7f1c547..5d5aa60f4a0fb 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -848,6 +848,7 @@ function(_add_swift_library_single target name) handle_gyb_sources( gyb_dependency_targets SWIFTLIB_SINGLE_SOURCES + "${SWIFTLIB_SINGLE_SDK}" "${SWIFTLIB_SINGLE_ARCHITECTURE}") if (SWIFT_RUNTIME_ENABLE_DTRACE) diff --git a/cmake/modules/SwiftHandleGybSources.cmake b/cmake/modules/SwiftHandleGybSources.cmake index d4350050ded63..ac9c45401fb77 100644 --- a/cmake/modules/SwiftHandleGybSources.cmake +++ b/cmake/modules/SwiftHandleGybSources.cmake @@ -17,19 +17,25 @@ include(SwiftSetIfArchBitness) # targets that invoke gyb. Every target that depends on the generated # sources should depend on ${dependency_out_var_name} targets. # +# sdk +# The platform ("IOS", "LINUX", "ANDROID") the files will be compiled for. +# If this is false, the files are platform-independent and will be emitted +# into ${CMAKE_CURRENT_BINARY_DIR}/${arch} instead of a platform-specific +# destination; this is useful for generated include files. +# # arch # The architecture that the files will be compiled for. If this is # false, the files are architecture-independent and will be emitted -# into ${CMAKE_CURRENT_BINARY_DIR} instead of an architecture-specific +# into ${CMAKE_CURRENT_BINARY_DIR}/${sdk} instead of an architecture-specific # destination; this is useful for generated include files. -function(handle_gyb_sources dependency_out_var_name sources_var_name arch) +function(handle_gyb_sources dependency_out_var_name sources_var_name sdk arch) set(extra_gyb_flags "") if (arch) set_if_arch_bitness(ptr_size ARCH "${arch}" CASE_32_BIT "4" CASE_64_BIT "8") - set(extra_gyb_flags "-DCMAKE_SIZEOF_VOID_P=${ptr_size}") + set(extra_gyb_flags "-DCMAKE_SIZEOF_VOID_P=${ptr_size}" "-DCMAKE_SDK=${sdk}") endif() set(gyb_flags @@ -52,10 +58,12 @@ function(handle_gyb_sources dependency_out_var_name sources_var_name arch) if(src STREQUAL src_sans_gyb) list(APPEND de_gybbed_sources "${src}") else() - if (arch) - set(dir "${CMAKE_CURRENT_BINARY_DIR}/${ptr_size}") - else() - set(dir "${CMAKE_CURRENT_BINARY_DIR}") + set(dir "${CMAKE_CURRENT_BINARY_DIR}") + if(sdk) + set(dir "${dir}/${ptr_size}") + endif() + if(arch) + set(dir "${dir}/${ptr_size}") endif() set(output_file_name "${dir}/${src_sans_gyb}") list(APPEND de_gybbed_sources "${output_file_name}") @@ -72,7 +80,7 @@ function(handle_gyb_sources dependency_out_var_name sources_var_name arch) "${CMAKE_COMMAND}" -E remove "${output_file_name}.tmp" OUTPUT "${output_file_name}" DEPENDS "${gyb_tool_source}" "${src}" "${gyb_extra_sources}" - COMMENT "Generating ${src_sans_gyb} from ${src} with ptr size = ${ptr_size}" + COMMENT "Generating ${src_sans_gyb} from ${src} with sdk = ${sdk} and ptr size = ${ptr_size}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" SOURCES "${src}" IDEMPOTENT) diff --git a/lib/ClangImporter/CMakeLists.txt b/lib/ClangImporter/CMakeLists.txt index 4ede274350af0..0d15276aaeec7 100644 --- a/lib/ClangImporter/CMakeLists.txt +++ b/lib/ClangImporter/CMakeLists.txt @@ -6,6 +6,7 @@ set(generated_include_sources SortedCFDatabase.def.gyb) handle_gyb_sources( generated_include_targets generated_include_sources + "" "") add_swift_library(swiftClangImporter diff --git a/stdlib/public/core/BuiltinMath.swift.gyb b/stdlib/public/core/BuiltinMath.swift.gyb index 9c84e6b01262a..f5163adacd84b 100644 --- a/stdlib/public/core/BuiltinMath.swift.gyb +++ b/stdlib/public/core/BuiltinMath.swift.gyb @@ -48,10 +48,15 @@ def cFuncSuffix(bits): UnaryIntrinsicFunctions = [ 'cos', 'sin', 'exp', 'exp2', - 'log', 'log10', 'log2', + 'log', 'log10', 'fabs', 'ceil', 'floor', 'nearbyint', 'rint', 'round', 'trunc', ] +# Android doesn't have a native log2 function. +# FIXME: Incorporate an implementation that works with Swift's license, +# or implement one ourselves in 'stdlib/public/stubs'. +if CMAKE_SDK != "ANDROID": + UnaryIntrinsicFunctions += ['log2'] def TypedUnaryIntrinsicFunctions(): for ufunc in UnaryIntrinsicFunctions: diff --git a/stdlib/public/stubs/CMakeLists.txt b/stdlib/public/stubs/CMakeLists.txt index 4de51baec354e..4bc5c74342161 100644 --- a/stdlib/public/stubs/CMakeLists.txt +++ b/stdlib/public/stubs/CMakeLists.txt @@ -25,8 +25,6 @@ add_swift_library(swiftStdlibStubs IS_STDLIB IS_STDLIB_CORE LibcShims.cpp Stubs.cpp UnicodeExtendedGraphemeClusters.cpp.gyb - android_support/Android_log2.cpp - android_support/Android_log2f.cpp ${swift_stubs_objc_sources} ${swift_stubs_unicode_normalization_sources} C_COMPILE_FLAGS ${SWIFT_CORE_CXX_FLAGS} diff --git a/stdlib/public/stubs/android_support/Android_log2.cpp b/stdlib/public/stubs/android_support/Android_log2.cpp deleted file mode 100644 index 6c99f14a3db90..0000000000000 --- a/stdlib/public/stubs/android_support/Android_log2.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __ANDROID__ -extern "C" { -#include "e_log2.c" -} -#endif diff --git a/stdlib/public/stubs/android_support/Android_log2f.cpp b/stdlib/public/stubs/android_support/Android_log2f.cpp deleted file mode 100644 index a8ac93dd2e2f1..0000000000000 --- a/stdlib/public/stubs/android_support/Android_log2f.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#ifdef __ANDROID__ -extern "C" { -#include "e_log2f.c" -} -#endif diff --git a/stdlib/public/stubs/android_support/e_log2.c b/stdlib/public/stubs/android_support/e_log2.c deleted file mode 100644 index 5d69771b8d4bd..0000000000000 --- a/stdlib/public/stubs/android_support/e_log2.c +++ /dev/null @@ -1,120 +0,0 @@ - -/* @(#)e_log10.c 1.3 95/01/18 */ -/* - * ==================================================== - * 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 -__FBSDID("$FreeBSD$"); - -/* - * Return the base 2 logarithm of x. See e_log.c and k_log.h for most - * comments. - * - * This reduces x to {k, 1+f} exactly as in e_log.c, then calls the kernel, - * then does the combining and scaling steps - * log2(x) = (f - 0.5*f*f + k_log1p(f)) / ln2 + k - * in not-quite-routine extra precision. - */ - -#include - -#include "math.h" -#include "math_private.h" -#include "k_log.h" - -static const double -two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ -ivln2hi = 1.44269504072144627571e+00, /* 0x3ff71547, 0x65200000 */ -ivln2lo = 1.67517131648865118353e-10; /* 0x3de705fc, 0x2eefa200 */ - -static const double zero = 0.0; -static volatile double vzero = 0.0; - -double -__ieee754_log2(double x) -{ - double f,hfsq,hi,lo,r,val_hi,val_lo,w,y; - int32_t i,k,hx; - u_int32_t lx; - - EXTRACT_WORDS(hx,lx,x); - - k=0; - if (hx < 0x00100000) { /* x < 2**-1022 */ - if (((hx&0x7fffffff)|lx)==0) - return -two54/vzero; /* log(+-0)=-inf */ - if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ - k -= 54; x *= two54; /* subnormal number, scale up x */ - GET_HIGH_WORD(hx,x); - } - if (hx >= 0x7ff00000) return x+x; - if (hx == 0x3ff00000 && lx == 0) - return zero; /* log(1) = +0 */ - k += (hx>>20)-1023; - hx &= 0x000fffff; - i = (hx+0x95f64)&0x100000; - SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ - k += (i>>20); - y = (double)k; - f = x - 1.0; - hfsq = 0.5*f*f; - r = k_log1p(f); - - /* - * f-hfsq must (for args near 1) be evaluated in extra precision - * to avoid a large cancellation when x is near sqrt(2) or 1/sqrt(2). - * This is fairly efficient since f-hfsq only depends on f, so can - * be evaluated in parallel with R. Not combining hfsq with R also - * keeps R small (though not as small as a true `lo' term would be), - * so that extra precision is not needed for terms involving R. - * - * Compiler bugs involving extra precision used to break Dekker's - * theorem for spitting f-hfsq as hi+lo, unless double_t was used - * or the multi-precision calculations were avoided when double_t - * has extra precision. These problems are now automatically - * avoided as a side effect of the optimization of combining the - * Dekker splitting step with the clear-low-bits step. - * - * y must (for args near sqrt(2) and 1/sqrt(2)) be added in extra - * precision to avoid a very large cancellation when x is very near - * these values. Unlike the above cancellations, this problem is - * specific to base 2. It is strange that adding +-1 is so much - * harder than adding +-ln2 or +-log10_2. - * - * This uses Dekker's theorem to normalize y+val_hi, so the - * compiler bugs are back in some configurations, sigh. And I - * don't want to used double_t to avoid them, since that gives a - * pessimization and the support for avoiding the pessimization - * is not yet available. - * - * The multi-precision calculations for the multiplications are - * routine. - */ - hi = f - hfsq; - SET_LOW_WORD(hi,0); - lo = (f - hi) - hfsq + r; - val_hi = hi*ivln2hi; - val_lo = (lo+hi)*ivln2lo + lo*ivln2hi; - - /* spadd(val_hi, val_lo, y), except for not using double_t: */ - w = y + val_hi; - val_lo += (y - w) + val_hi; - val_hi = w; - - return val_lo + val_hi; -} - -#if (LDBL_MANT_DIG == 53) && !defined(__le32__) && !defined(__le64__) -#define __weak_reference(sym,alias) \ - __asm__(".weak " #alias); \ - __asm__(".equ " #alias ", " #sym) -__weak_reference(log2, log2l); -#endif diff --git a/stdlib/public/stubs/android_support/e_log2f.c b/stdlib/public/stubs/android_support/e_log2f.c deleted file mode 100644 index 1794484e64ecc..0000000000000 --- a/stdlib/public/stubs/android_support/e_log2f.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ==================================================== - * 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 -__FBSDID("$FreeBSD$"); - -/* - * Float version of e_log2.c. See the latter for most comments. - */ - -#include "math.h" -#include "math_private.h" -#include "k_logf.h" - -static const float -two25 = 3.3554432000e+07, /* 0x4c000000 */ -ivln2hi = 1.4428710938e+00, /* 0x3fb8b000 */ -ivln2lo = -1.7605285393e-04; /* 0xb9389ad4 */ - -static const float zero = 0.0; -static volatile float vzero = 0.0; - -float -__ieee754_log2f(float x) -{ - float f,hfsq,hi,lo,r,y; - int32_t i,k,hx; - - GET_FLOAT_WORD(hx,x); - - k=0; - if (hx < 0x00800000) { /* x < 2**-126 */ - if ((hx&0x7fffffff)==0) - return -two25/vzero; /* log(+-0)=-inf */ - if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ - k -= 25; x *= two25; /* subnormal number, scale up x */ - GET_FLOAT_WORD(hx,x); - } - if (hx >= 0x7f800000) return x+x; - if (hx == 0x3f800000) - return zero; /* log(1) = +0 */ - k += (hx>>23)-127; - hx &= 0x007fffff; - i = (hx+(0x4afb0d))&0x800000; - SET_FLOAT_WORD(x,hx|(i^0x3f800000)); /* normalize x or x/2 */ - k += (i>>23); - y = (float)k; - f = x - (float)1.0; - hfsq = (float)0.5*f*f; - r = k_log1pf(f); - - /* - * We no longer need to avoid falling into the multi-precision - * calculations due to compiler bugs breaking Dekker's theorem. - * Keep avoiding this as an optimization. See e_log2.c for more - * details (some details are here only because the optimization - * is not yet available in double precision). - * - * Another compiler bug turned up. With gcc on i386, - * (ivln2lo + ivln2hi) would be evaluated in float precision - * despite runtime evaluations using double precision. So we - * must cast one of its terms to float_t. This makes the whole - * expression have type float_t, so return is forced to waste - * time clobbering its extra precision. - */ - if (sizeof(float_t) > sizeof(float)) - return (r - hfsq + f) * ((float_t)ivln2lo + ivln2hi) + y; - - hi = f - hfsq; - GET_FLOAT_WORD(hx,hi); - SET_FLOAT_WORD(hi,hx&0xfffff000); - lo = (f - hi) - hfsq + r; - return (lo+hi)*ivln2lo + lo*ivln2hi + hi*ivln2hi + y; -} diff --git a/stdlib/public/stubs/android_support/k_log.h b/stdlib/public/stubs/android_support/k_log.h deleted file mode 100644 index aaff8bd9000e7..0000000000000 --- a/stdlib/public/stubs/android_support/k_log.h +++ /dev/null @@ -1,100 +0,0 @@ - -/* @(#)e_log.c 1.3 95/01/18 */ -/* - * ==================================================== - * 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 -__FBSDID("$FreeBSD$"); - -/* - * k_log1p(f): - * Return log(1+f) - f for 1+f in ~[sqrt(2)/2, sqrt(2)]. - * - * The following describes the overall strategy for computing - * logarithms in base e. The argument reduction and adding the final - * term of the polynomial are done by the caller for increased accuracy - * when different bases are used. - * - * Method : - * 1. Argument Reduction: find k and f such that - * x = 2^k * (1+f), - * where sqrt(2)/2 < 1+f < sqrt(2) . - * - * 2. Approximation of log(1+f). - * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) - * = 2s + 2/3 s**3 + 2/5 s**5 + ....., - * = 2s + s*R - * We use a special Reme algorithm on [0,0.1716] to generate - * a polynomial of degree 14 to approximate R The maximum error - * of this polynomial approximation is bounded by 2**-58.45. In - * other words, - * 2 4 6 8 10 12 14 - * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s - * (the values of Lg1 to Lg7 are listed in the program) - * and - * | 2 14 | -58.45 - * | Lg1*s +...+Lg7*s - R(z) | <= 2 - * | | - * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. - * In order to guarantee error in log below 1ulp, we compute log - * by - * log(1+f) = f - s*(f - R) (if f is not too large) - * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) - * - * 3. Finally, log(x) = k*ln2 + log(1+f). - * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) - * Here ln2 is split into two floating point number: - * ln2_hi + ln2_lo, - * where n*ln2_hi is always exact for |n| < 2000. - * - * Special cases: - * log(x) is NaN with signal if x < 0 (including -INF) ; - * log(+INF) is +INF; log(0) is -INF with signal; - * log(NaN) is that NaN with no signal. - * - * Accuracy: - * according to an error analysis, the error is always less than - * 1 ulp (unit in the last place). - * - * Constants: - * The hexadecimal values are the intended ones for the following - * constants. The decimal values may be used, provided that the - * compiler will convert from decimal to binary accurately enough - * to produce the hexadecimal values shown. - */ - -static const double -Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ -Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ -Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ -Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ -Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ -Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ -Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ - -/* - * We always inline k_log1p(), since doing so produces a - * substantial performance improvement (~40% on amd64). - */ -static inline double -k_log1p(double f) -{ - double hfsq,s,z,R,w,t1,t2; - - s = f/(2.0+f); - z = s*s; - w = z*z; - t1= w*(Lg2+w*(Lg4+w*Lg6)); - t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); - R = t2+t1; - hfsq=0.5*f*f; - return s*(hfsq+R); -} diff --git a/stdlib/public/stubs/android_support/k_logf.h b/stdlib/public/stubs/android_support/k_logf.h deleted file mode 100644 index 71c547e888ae6..0000000000000 --- a/stdlib/public/stubs/android_support/k_logf.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * ==================================================== - * 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 -__FBSDID("$FreeBSD$"); - -/* - * Float version of k_log.h. See the latter for most comments. - */ - -static const float -/* |(log(1+s)-log(1-s))/s - Lg(s)| < 2**-34.24 (~[-4.95e-11, 4.97e-11]). */ -Lg1 = 0xaaaaaa.0p-24, /* 0.66666662693 */ -Lg2 = 0xccce13.0p-25, /* 0.40000972152 */ -Lg3 = 0x91e9ee.0p-25, /* 0.28498786688 */ -Lg4 = 0xf89e26.0p-26; /* 0.24279078841 */ - -static inline float -k_log1pf(float f) -{ - float hfsq,s,z,R,w,t1,t2; - - s = f/((float)2.0+f); - z = s*s; - w = z*z; - t1= w*(Lg2+w*Lg4); - t2= z*(Lg1+w*Lg3); - R = t2+t1; - hfsq=(float)0.5*f*f; - return s*(hfsq+R); -} diff --git a/stdlib/public/stubs/android_support/math_private.h b/stdlib/public/stubs/android_support/math_private.h deleted file mode 100644 index 8ebc7fbf30c8e..0000000000000 --- a/stdlib/public/stubs/android_support/math_private.h +++ /dev/null @@ -1,764 +0,0 @@ -/* - * ==================================================== - * 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. - * ==================================================== - */ - -/* - * from: @(#)fdlibm.h 5.1 93/09/24 - * $FreeBSD$ - */ - -#ifndef _MATH_PRIVATE_H_ -#define _MATH_PRIVATE_H_ - -#include -#include - -/* - * The original fdlibm code used statements like: - * n0 = ((*(int*)&one)>>29)^1; * index of high word * - * ix0 = *(n0+(int*)&x); * high word of x * - * ix1 = *((1-n0)+(int*)&x); * low word of x * - * to dig two 32 bit words out of the 64 bit IEEE floating point - * value. That is non-ANSI, and, moreover, the gcc instruction - * scheduler gets it wrong. We instead use the following macros. - * Unlike the original code, we determine the endianness at compile - * time, not at run time; I don't see much benefit to selecting - * endianness at run time. - */ - -/* - * A union which permits us to convert between a double and two 32 bit - * ints. - */ - -#ifdef __arm__ -#if defined(__VFP_FP__) -#define IEEE_WORD_ORDER BYTE_ORDER -#else -#define IEEE_WORD_ORDER BIG_ENDIAN -#endif -#else /* __arm__ */ -#define IEEE_WORD_ORDER BYTE_ORDER -#endif - -#if IEEE_WORD_ORDER == BIG_ENDIAN - -typedef union -{ - double value; - struct - { - u_int32_t msw; - u_int32_t lsw; - } parts; - struct - { - u_int64_t w; - } xparts; -} ieee_double_shape_type; - -#endif - -#if IEEE_WORD_ORDER == LITTLE_ENDIAN - -typedef union -{ - double value; - struct - { - u_int32_t lsw; - u_int32_t msw; - } parts; - struct - { - u_int64_t w; - } xparts; -} ieee_double_shape_type; - -#endif - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS(ix0,ix1,d) \ -do { \ - ieee_double_shape_type ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ -} while (0) - -/* Get a 64-bit int from a double. */ -#define EXTRACT_WORD64(ix,d) \ -do { \ - ieee_double_shape_type ew_u; \ - ew_u.value = (d); \ - (ix) = ew_u.xparts.w; \ -} while (0) - -/* Get the more significant 32 bit int from a double. */ - -#define GET_HIGH_WORD(i,d) \ -do { \ - ieee_double_shape_type gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ -} while (0) - -/* Get the less significant 32 bit int from a double. */ - -#define GET_LOW_WORD(i,d) \ -do { \ - ieee_double_shape_type gl_u; \ - gl_u.value = (d); \ - (i) = gl_u.parts.lsw; \ -} while (0) - -/* Set a double from two 32 bit ints. */ - -#define INSERT_WORDS(d,ix0,ix1) \ -do { \ - ieee_double_shape_type iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ -} while (0) - -/* Set a double from a 64-bit int. */ -#define INSERT_WORD64(d,ix) \ -do { \ - ieee_double_shape_type iw_u; \ - iw_u.xparts.w = (ix); \ - (d) = iw_u.value; \ -} while (0) - -/* Set the more significant 32 bits of a double from an int. */ - -#define SET_HIGH_WORD(d,v) \ -do { \ - ieee_double_shape_type sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ -} while (0) - -/* Set the less significant 32 bits of a double from an int. */ - -#define SET_LOW_WORD(d,v) \ -do { \ - ieee_double_shape_type sl_u; \ - sl_u.value = (d); \ - sl_u.parts.lsw = (v); \ - (d) = sl_u.value; \ -} while (0) - -/* - * A union which permits us to convert between a float and a 32 bit - * int. - */ - -typedef union -{ - float value; - /* FIXME: Assumes 32 bit int. */ - unsigned int word; -} ieee_float_shape_type; - -/* Get a 32 bit int from a float. */ - -#define GET_FLOAT_WORD(i,d) \ -do { \ - ieee_float_shape_type gf_u; \ - gf_u.value = (d); \ - (i) = gf_u.word; \ -} while (0) - -/* Set a float from a 32 bit int. */ - -#define SET_FLOAT_WORD(d,i) \ -do { \ - ieee_float_shape_type sf_u; \ - sf_u.word = (i); \ - (d) = sf_u.value; \ -} while (0) - -/* - * Get expsign and mantissa as 16 bit and 64 bit ints from an 80 bit long - * double. - */ - -#define EXTRACT_LDBL80_WORDS(ix0,ix1,d) \ -do { \ - union IEEEl2bits ew_u; \ - ew_u.e = (d); \ - (ix0) = ew_u.xbits.expsign; \ - (ix1) = ew_u.xbits.man; \ -} while (0) - -/* - * Get expsign and mantissa as one 16 bit and two 64 bit ints from a 128 bit - * long double. - */ - -#define EXTRACT_LDBL128_WORDS(ix0,ix1,ix2,d) \ -do { \ - union IEEEl2bits ew_u; \ - ew_u.e = (d); \ - (ix0) = ew_u.xbits.expsign; \ - (ix1) = ew_u.xbits.manh; \ - (ix2) = ew_u.xbits.manl; \ -} while (0) - -/* Get expsign as a 16 bit int from a long double. */ - -#define GET_LDBL_EXPSIGN(i,d) \ -do { \ - union IEEEl2bits ge_u; \ - ge_u.e = (d); \ - (i) = ge_u.xbits.expsign; \ -} while (0) - -/* - * Set an 80 bit long double from a 16 bit int expsign and a 64 bit int - * mantissa. - */ - -#define INSERT_LDBL80_WORDS(d,ix0,ix1) \ -do { \ - union IEEEl2bits iw_u; \ - iw_u.xbits.expsign = (ix0); \ - iw_u.xbits.man = (ix1); \ - (d) = iw_u.e; \ -} while (0) - -/* - * Set a 128 bit long double from a 16 bit int expsign and two 64 bit ints - * comprising the mantissa. - */ - -#define INSERT_LDBL128_WORDS(d,ix0,ix1,ix2) \ -do { \ - union IEEEl2bits iw_u; \ - iw_u.xbits.expsign = (ix0); \ - iw_u.xbits.manh = (ix1); \ - iw_u.xbits.manl = (ix2); \ - (d) = iw_u.e; \ -} while (0) - -/* Set expsign of a long double from a 16 bit int. */ - -#define SET_LDBL_EXPSIGN(d,v) \ -do { \ - union IEEEl2bits se_u; \ - se_u.e = (d); \ - se_u.xbits.expsign = (v); \ - (d) = se_u.e; \ -} while (0) - -#ifdef __i386__ -/* Long double constants are broken on i386. */ -#define LD80C(m, ex, v) { \ - .xbits.man = __CONCAT(m, ULL), \ - .xbits.expsign = (0x3fff + (ex)) | ((v) < 0 ? 0x8000 : 0), \ -} -#else -/* The above works on non-i386 too, but we use this to check v. */ -#define LD80C(m, ex, v) { .e = (v), } -#endif - -#ifdef FLT_EVAL_METHOD -/* - * Attempt to get strict C99 semantics for assignment with non-C99 compilers. - */ -#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 -#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) -#else -#define STRICT_ASSIGN(type, lval, rval) do { \ - volatile type __lval; \ - \ - if (sizeof(type) >= sizeof(long double)) \ - (lval) = (rval); \ - else { \ - __lval = (rval); \ - (lval) = __lval; \ - } \ -} while (0) -#endif -#endif /* FLT_EVAL_METHOD */ - -/* Support switching the mode to FP_PE if necessary. */ -#if defined(__i386__) && !defined(NO_FPSETPREC) -#define ENTERI() \ - long double __retval; \ - fp_prec_t __oprec; \ - \ - if ((__oprec = fpgetprec()) != FP_PE) \ - fpsetprec(FP_PE) -#define RETURNI(x) do { \ - __retval = (x); \ - if (__oprec != FP_PE) \ - fpsetprec(__oprec); \ - RETURNF(__retval); \ -} while (0) -#else -#define ENTERI(x) -#define RETURNI(x) RETURNF(x) -#endif - -/* Default return statement if hack*_t() is not used. */ -#define RETURNF(v) return (v) - -/* - * 2sum gives the same result as 2sumF without requiring |a| >= |b| or - * a == 0, but is slower. - */ -#define _2sum(a, b) do { \ - __typeof(a) __s, __w; \ - \ - __w = (a) + (b); \ - __s = __w - (a); \ - (b) = ((a) - (__w - __s)) + ((b) - __s); \ - (a) = __w; \ -} while (0) - -/* - * 2sumF algorithm. - * - * "Normalize" the terms in the infinite-precision expression a + b for - * the sum of 2 floating point values so that b is as small as possible - * relative to 'a'. (The resulting 'a' is the value of the expression in - * the same precision as 'a' and the resulting b is the rounding error.) - * |a| must be >= |b| or 0, b's type must be no larger than 'a's type, and - * exponent overflow or underflow must not occur. This uses a Theorem of - * Dekker (1971). See Knuth (1981) 4.2.2 Theorem C. The name "TwoSum" - * is apparently due to Skewchuk (1997). - * - * For this to always work, assignment of a + b to 'a' must not retain any - * extra precision in a + b. This is required by C standards but broken - * in many compilers. The brokenness cannot be worked around using - * STRICT_ASSIGN() like we do elsewhere, since the efficiency of this - * algorithm would be destroyed by non-null strict assignments. (The - * compilers are correct to be broken -- the efficiency of all floating - * point code calculations would be destroyed similarly if they forced the - * conversions.) - * - * Fortunately, a case that works well can usually be arranged by building - * any extra precision into the type of 'a' -- 'a' should have type float_t, - * double_t or long double. b's type should be no larger than 'a's type. - * Callers should use these types with scopes as large as possible, to - * reduce their own extra-precision and efficiciency problems. In - * particular, they shouldn't convert back and forth just to call here. - */ -#ifdef DEBUG -#define _2sumF(a, b) do { \ - __typeof(a) __w; \ - volatile __typeof(a) __ia, __ib, __r, __vw; \ - \ - __ia = (a); \ - __ib = (b); \ - assert(__ia == 0 || fabsl(__ia) >= fabsl(__ib)); \ - \ - __w = (a) + (b); \ - (b) = ((a) - __w) + (b); \ - (a) = __w; \ - \ - /* The next 2 assertions are weak if (a) is already long double. */ \ - assert((long double)__ia + __ib == (long double)(a) + (b)); \ - __vw = __ia + __ib; \ - __r = __ia - __vw; \ - __r += __ib; \ - assert(__vw == (a) && __r == (b)); \ -} while (0) -#else /* !DEBUG */ -#define _2sumF(a, b) do { \ - __typeof(a) __w; \ - \ - __w = (a) + (b); \ - (b) = ((a) - __w) + (b); \ - (a) = __w; \ -} while (0) -#endif /* DEBUG */ - -/* - * Set x += c, where x is represented in extra precision as a + b. - * x must be sufficiently normalized and sufficiently larger than c, - * and the result is then sufficiently normalized. - * - * The details of ordering are that |a| must be >= |c| (so that (a, c) - * can be normalized without extra work to swap 'a' with c). The details of - * the normalization are that b must be small relative to the normalized 'a'. - * Normalization of (a, c) makes the normalized c tiny relative to the - * normalized a, so b remains small relative to 'a' in the result. However, - * b need not ever be tiny relative to 'a'. For example, b might be about - * 2**20 times smaller than 'a' to give about 20 extra bits of precision. - * That is usually enough, and adding c (which by normalization is about - * 2**53 times smaller than a) cannot change b significantly. However, - * cancellation of 'a' with c in normalization of (a, c) may reduce 'a' - * significantly relative to b. The caller must ensure that significant - * cancellation doesn't occur, either by having c of the same sign as 'a', - * or by having |c| a few percent smaller than |a|. Pre-normalization of - * (a, b) may help. - * - * This is is a variant of an algorithm of Kahan (see Knuth (1981) 4.2.2 - * exercise 19). We gain considerable efficiency by requiring the terms to - * be sufficiently normalized and sufficiently increasing. - */ -#define _3sumF(a, b, c) do { \ - __typeof(a) __tmp; \ - \ - __tmp = (c); \ - _2sumF(__tmp, (a)); \ - (b) += (a); \ - (a) = __tmp; \ -} while (0) - -/* - * Common routine to process the arguments to nan(), nanf(), and nanl(). - */ -void _scan_nan(uint32_t *__words, int __num_words, const char *__s); - -#ifdef _COMPLEX_H - -/* - * C99 specifies that complex numbers have the same representation as - * an array of two elements, where the first element is the real part - * and the second element is the imaginary part. - */ -typedef union { - float complex f; - float a[2]; -} float_complex; -typedef union { - double complex f; - double a[2]; -} double_complex; -typedef union { - long double complex f; - long double a[2]; -} long_double_complex; -#define REALPART(z) ((z).a[0]) -#define IMAGPART(z) ((z).a[1]) - -/* - * Inline functions that can be used to construct complex values. - * - * The C99 standard intends x+I*y to be used for this, but x+I*y is - * currently unusable in general since gcc introduces many overflow, - * underflow, sign and efficiency bugs by rewriting I*y as - * (0.0+I)*(y+0.0*I) and laboriously computing the full complex product. - * In particular, I*Inf is corrupted to NaN+I*Inf, and I*-0 is corrupted - * to -0.0+I*0.0. - */ -static __inline float complex -cpackf(float x, float y) -{ - float_complex z; - - REALPART(z) = x; - IMAGPART(z) = y; - return (z.f); -} - -static __inline double complex -cpack(double x, double y) -{ - double_complex z; - - REALPART(z) = x; - IMAGPART(z) = y; - return (z.f); -} - -static __inline long double complex -cpackl(long double x, long double y) -{ - long_double_complex z; - - REALPART(z) = x; - IMAGPART(z) = y; - return (z.f); -} -#endif /* _COMPLEX_H */ - -#ifdef __GNUCLIKE_ASM - -/* Asm versions of some functions. */ - -#ifdef __amd64__ -static __inline int -irint(double x) -{ - int n; - - asm("cvtsd2si %1,%0" : "=r" (n) : "x" (x)); - return (n); -} -#define HAVE_EFFICIENT_IRINT -#endif - -#ifdef __i386__ -static __inline int -irint(double x) -{ - int n; - - asm("fistl %0" : "=m" (n) : "t" (x)); - return (n); -} -#define HAVE_EFFICIENT_IRINT -#endif - -#if defined(__amd64__) || defined(__i386__) -static __inline int -irintl(long double x) -{ - int n; - - asm("fistl %0" : "=m" (n) : "t" (x)); - return (n); -} -#define HAVE_EFFICIENT_IRINTL -#endif - -#endif /* __GNUCLIKE_ASM */ - -#ifdef DEBUG -#if defined(__amd64__) || defined(__i386__) -#define breakpoint() asm("int $3") -#else -#include - -#define breakpoint() raise(SIGTRAP) -#endif -#endif - -/* Write a pari script to test things externally. */ -#ifdef DOPRINT -#include - -#ifndef DOPRINT_SWIZZLE -#define DOPRINT_SWIZZLE 0 -#endif - -#ifdef DOPRINT_LD80 - -#define DOPRINT_START(xp) do { \ - uint64_t __lx; \ - uint16_t __hx; \ - \ - /* Hack to give more-problematic args. */ \ - EXTRACT_LDBL80_WORDS(__hx, __lx, *xp); \ - __lx ^= DOPRINT_SWIZZLE; \ - INSERT_LDBL80_WORDS(*xp, __hx, __lx); \ - printf("x = %.21Lg; ", (long double)*xp); \ -} while (0) -#define DOPRINT_END1(v) \ - printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v)) -#define DOPRINT_END2(hi, lo) \ - printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n", \ - (long double)(hi), (long double)(lo)) - -#elif defined(DOPRINT_D64) - -#define DOPRINT_START(xp) do { \ - uint32_t __hx, __lx; \ - \ - EXTRACT_WORDS(__hx, __lx, *xp); \ - __lx ^= DOPRINT_SWIZZLE; \ - INSERT_WORDS(*xp, __hx, __lx); \ - printf("x = %.21Lg; ", (long double)*xp); \ -} while (0) -#define DOPRINT_END1(v) \ - printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v)) -#define DOPRINT_END2(hi, lo) \ - printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n", \ - (long double)(hi), (long double)(lo)) - -#elif defined(DOPRINT_F32) - -#define DOPRINT_START(xp) do { \ - uint32_t __hx; \ - \ - GET_FLOAT_WORD(__hx, *xp); \ - __hx ^= DOPRINT_SWIZZLE; \ - SET_FLOAT_WORD(*xp, __hx); \ - printf("x = %.21Lg; ", (long double)*xp); \ -} while (0) -#define DOPRINT_END1(v) \ - printf("y = %.21Lg; z = 0; show(x, y, z);\n", (long double)(v)) -#define DOPRINT_END2(hi, lo) \ - printf("y = %.21Lg; z = %.21Lg; show(x, y, z);\n", \ - (long double)(hi), (long double)(lo)) - -#else /* !DOPRINT_LD80 && !DOPRINT_D64 (LD128 only) */ - -#ifndef DOPRINT_SWIZZLE_HIGH -#define DOPRINT_SWIZZLE_HIGH 0 -#endif - -#define DOPRINT_START(xp) do { \ - uint64_t __lx, __llx; \ - uint16_t __hx; \ - \ - EXTRACT_LDBL128_WORDS(__hx, __lx, __llx, *xp); \ - __llx ^= DOPRINT_SWIZZLE; \ - __lx ^= DOPRINT_SWIZZLE_HIGH; \ - INSERT_LDBL128_WORDS(*xp, __hx, __lx, __llx); \ - printf("x = %.36Lg; ", (long double)*xp); \ -} while (0) -#define DOPRINT_END1(v) \ - printf("y = %.36Lg; z = 0; show(x, y, z);\n", (long double)(v)) -#define DOPRINT_END2(hi, lo) \ - printf("y = %.36Lg; z = %.36Lg; show(x, y, z);\n", \ - (long double)(hi), (long double)(lo)) - -#endif /* DOPRINT_LD80 */ - -#else /* !DOPRINT */ -#define DOPRINT_START(xp) -#define DOPRINT_END1(v) -#define DOPRINT_END2(hi, lo) -#endif /* DOPRINT */ - -#define RETURNP(x) do { \ - DOPRINT_END1(x); \ - RETURNF(x); \ -} while (0) -#define RETURNPI(x) do { \ - DOPRINT_END1(x); \ - RETURNI(x); \ -} while (0) -#define RETURN2P(x, y) do { \ - DOPRINT_END2((x), (y)); \ - RETURNF((x) + (y)); \ -} while (0) -#define RETURN2PI(x, y) do { \ - DOPRINT_END2((x), (y)); \ - RETURNI((x) + (y)); \ -} while (0) -#ifdef STRUCT_RETURN -#define RETURNSP(rp) do { \ - if (!(rp)->lo_set) \ - RETURNP((rp)->hi); \ - RETURN2P((rp)->hi, (rp)->lo); \ -} while (0) -#define RETURNSPI(rp) do { \ - if (!(rp)->lo_set) \ - RETURNPI((rp)->hi); \ - RETURN2PI((rp)->hi, (rp)->lo); \ -} while (0) -#endif -#define SUM2P(x, y) ({ \ - const __typeof (x) __x = (x); \ - const __typeof (y) __y = (y); \ - \ - DOPRINT_END2(__x, __y); \ - __x + __y; \ -}) - -/* - * ieee style elementary functions - * - * We rename functions here to improve other sources' diffability - * against fdlibm. - */ -#define __ieee754_sqrt sqrt -#define __ieee754_acos acos -#define __ieee754_acosh acosh -#define __ieee754_log log -#define __ieee754_log2 log2 -#define __ieee754_atanh atanh -#define __ieee754_asin asin -#define __ieee754_atan2 atan2 -#define __ieee754_exp exp -#define __ieee754_cosh cosh -#define __ieee754_fmod fmod -#define __ieee754_pow pow -#define __ieee754_lgamma lgamma -#define __ieee754_gamma gamma -#define __ieee754_lgamma_r lgamma_r -#define __ieee754_gamma_r gamma_r -#define __ieee754_log10 log10 -#define __ieee754_sinh sinh -#define __ieee754_hypot hypot -#define __ieee754_j0 j0 -#define __ieee754_j1 j1 -#define __ieee754_y0 y0 -#define __ieee754_y1 y1 -#define __ieee754_jn jn -#define __ieee754_yn yn -#define __ieee754_remainder remainder -#define __ieee754_scalb scalb -#define __ieee754_sqrtf sqrtf -#define __ieee754_acosf acosf -#define __ieee754_acoshf acoshf -#define __ieee754_logf logf -#define __ieee754_atanhf atanhf -#define __ieee754_asinf asinf -#define __ieee754_atan2f atan2f -#define __ieee754_expf expf -#define __ieee754_coshf coshf -#define __ieee754_fmodf fmodf -#define __ieee754_powf powf -#define __ieee754_lgammaf lgammaf -#define __ieee754_gammaf gammaf -#define __ieee754_lgammaf_r lgammaf_r -#define __ieee754_gammaf_r gammaf_r -#define __ieee754_log10f log10f -#define __ieee754_log2f log2f -#define __ieee754_sinhf sinhf -#define __ieee754_hypotf hypotf -#define __ieee754_j0f j0f -#define __ieee754_j1f j1f -#define __ieee754_y0f y0f -#define __ieee754_y1f y1f -#define __ieee754_jnf jnf -#define __ieee754_ynf ynf -#define __ieee754_remainderf remainderf -#define __ieee754_scalbf scalbf - -/* fdlibm kernel function */ -int __kernel_rem_pio2(double*,double*,int,int,int); - -/* double precision kernel functions */ -#ifndef INLINE_REM_PIO2 -int __ieee754_rem_pio2(double,double*); -#endif -double __kernel_sin(double,double,int); -double __kernel_cos(double,double); -double __kernel_tan(double,double,int); -double __ldexp_exp(double,int); -#ifdef _COMPLEX_H -double complex __ldexp_cexp(double complex,int); -#endif - -/* float precision kernel functions */ -#ifndef INLINE_REM_PIO2F -int __ieee754_rem_pio2f(float,double*); -#endif -#ifndef INLINE_KERNEL_SINDF -float __kernel_sindf(double); -#endif -#ifndef INLINE_KERNEL_COSDF -float __kernel_cosdf(double); -#endif -#ifndef INLINE_KERNEL_TANDF -float __kernel_tandf(double,int); -#endif -float __ldexp_expf(float,int); -#ifdef _COMPLEX_H -float complex __ldexp_cexpf(float complex,int); -#endif - -/* long double precision kernel functions */ -long double __kernel_sinl(long double, long double, int); -long double __kernel_cosl(long double, long double); -long double __kernel_tanl(long double, long double, int); - -#endif /* !_MATH_PRIVATE_H_ */ diff --git a/unittests/Basic/CMakeLists.txt b/unittests/Basic/CMakeLists.txt index 120f2c37694fc..8e75ae5bd7b79 100644 --- a/unittests/Basic/CMakeLists.txt +++ b/unittests/Basic/CMakeLists.txt @@ -3,6 +3,7 @@ set(generated_tests UnicodeGraphemeBreakTest.cpp.gyb) handle_gyb_sources( gyb_dependency_targets generated_tests + "" ${SWIFT_HOST_VARIANT_ARCH}) add_swift_unittest(SwiftBasicTests