[builtins] Support building the 128-bit float functions on ld80 platforms (#68132)

GCC provides these functions (e.g. __addtf3, etc.) in libgcc on x86_64.
Since Clang supports float128, we can also enable the existing code by
using float128 for fp_t if either __FLOAT128__ or __SIZEOF_FLOAT128__ is
defined instead of only supporting these builtins for platforms with
128-bit IEEE long doubles.
This commit defines a new tf_float typedef that matches a float with
attribute((mode(TF)) on each given architecture.

There are more tests that could be enabled for x86, but to keep the diff
smaller, I restricted test changes to ones that started failing as part
of this refactoring.

This change has been tested on x86 (natively) and
aarch64,powerpc64,riscv64 and sparc64 via qemu-user.

This supersedes https://reviews.llvm.org/D98261 and should also cover
the changes from https://github.com/llvm/llvm-project/pull/68041.
This commit is contained in:
Alexander Richardson 2023-10-24 09:32:01 -07:00 committed by GitHub
parent 16fe53c47e
commit d2ce3e9621
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 1055 additions and 949 deletions

View File

@ -187,8 +187,6 @@ set(BF16_SOURCES
truncsfbf2.c
)
# TODO: Several "tf" files (and divtc3.c, but not multc3.c) are in
# GENERIC_SOURCES instead of here.
set(GENERIC_TF_SOURCES
addtf3.c
comparetf2.c

View File

@ -137,49 +137,54 @@ si_int __ucmpti2(tu_int a, tu_int b);
di_int __fixsfdi( float a);
di_int __fixdfdi( double a);
di_int __fixxfdi(long double a);
di_int __fixtfdi( tf_float a);
ti_int __fixsfti( float a);
ti_int __fixdfti( double a);
ti_int __fixxfti(long double a);
uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation
ti_int __fixtfti( tf_float a);
su_int __fixunssfsi( float a);
su_int __fixunsdfsi( double a);
su_int __fixunsxfsi(long double a);
su_int __fixunstfsi( tf_float a);
du_int __fixunssfdi( float a);
du_int __fixunsdfdi( double a);
du_int __fixunsxfdi(long double a);
du_int __fixunstfdi( tf_float a);
tu_int __fixunssfti( float a);
tu_int __fixunsdfti( double a);
tu_int __fixunsxfti(long double a);
uint64_t __fixunstfdi(long double input); // ppc only
tu_int __fixunstfti( tf_float a);
float __floatdisf(di_int a);
double __floatdidf(di_int a);
long double __floatdixf(di_int a);
long double __floatditf(int64_t a); // ppc only
tf_float __floatditf(int64_t a);
float __floattisf(ti_int a);
double __floattidf(ti_int a);
long double __floattixf(ti_int a);
tf_float __floattitf(ti_int a);
float __floatundisf(du_int a);
double __floatundidf(du_int a);
long double __floatundixf(du_int a);
long double __floatunditf(uint64_t a); // ppc only
tf_float __floatunditf(du_int a);
float __floatuntisf(tu_int a);
double __floatuntidf(tu_int a);
long double __floatuntixf(tu_int a);
tf_float __floatuntixf(tu_int a);
// Floating point raised to integer power
float __powisf2( float a, int b); // a ^ b
double __powidf2( double a, int b); // a ^ b
long double __powixf2(long double a, int b); // a ^ b
long double __powitf2(long double a, int b); // ppc only, a ^ b
tf_float __powitf2( tf_float a, int b); // a ^ b
// Complex arithmetic
@ -189,8 +194,7 @@ long double __powitf2(long double a, int b); // ppc only, a ^ b
double _Complex __muldc3(double a, double b, double c, double d);
long double _Complex __mulxc3(long double a, long double b,
long double c, long double d);
long double _Complex __multc3(long double a, long double b,
long double c, long double d); // ppc only
tf_float _Complex __multc3(tf_float a, tf_float b, tf_float c, tf_float d);
// (a + ib) / (c + id)
@ -198,8 +202,7 @@ long double _Complex __multc3(long double a, long double b,
double _Complex __divdc3(double a, double b, double c, double d);
long double _Complex __divxc3(long double a, long double b,
long double c, long double d);
long double _Complex __divtc3(long double a, long double b,
long double c, long double d); // ppc only
tf_float _Complex __divtc3(tf_float a, tf_float b, tf_float c, tf_float d);
// Runtime support

View File

@ -12,44 +12,45 @@
#define QUAD_PRECISION
#include "fp_lib.h"
#include "int_lib.h"
#include "int_math.h"
#if defined(CRT_HAS_TF_MODE)
// Returns: the quotient of (a + ib) / (c + id)
COMPILER_RT_ABI Lcomplex __divtc3(long double __a, long double __b,
long double __c, long double __d) {
COMPILER_RT_ABI Qcomplex __divtc3(fp_t __a, fp_t __b, fp_t __c, fp_t __d) {
int __ilogbw = 0;
long double __logbw =
__compiler_rt_logbl(__compiler_rt_fmaxl(crt_fabsl(__c), crt_fabsl(__d)));
fp_t __logbw = __compiler_rt_logbtf(
__compiler_rt_fmaxtf(crt_fabstf(__c), crt_fabstf(__d)));
if (crt_isfinite(__logbw)) {
__ilogbw = (int)__logbw;
__c = __compiler_rt_scalbnl(__c, -__ilogbw);
__d = __compiler_rt_scalbnl(__d, -__ilogbw);
__c = __compiler_rt_scalbntf(__c, -__ilogbw);
__d = __compiler_rt_scalbntf(__d, -__ilogbw);
}
long double __denom = __c * __c + __d * __d;
Lcomplex z;
COMPLEX_REAL(z) =
__compiler_rt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
COMPLEX_IMAGINARY(z) =
__compiler_rt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
if (crt_isnan(COMPLEX_REAL(z)) && crt_isnan(COMPLEX_IMAGINARY(z))) {
fp_t __denom = __c * __c + __d * __d;
Qcomplex z;
COMPLEXTF_REAL(z) =
__compiler_rt_scalbntf((__a * __c + __b * __d) / __denom, -__ilogbw);
COMPLEXTF_IMAGINARY(z) =
__compiler_rt_scalbntf((__b * __c - __a * __d) / __denom, -__ilogbw);
if (crt_isnan(COMPLEXTF_REAL(z)) && crt_isnan(COMPLEXTF_IMAGINARY(z))) {
if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b))) {
COMPLEX_REAL(z) = crt_copysignl(CRT_INFINITY, __c) * __a;
COMPLEX_IMAGINARY(z) = crt_copysignl(CRT_INFINITY, __c) * __b;
COMPLEXTF_REAL(z) = crt_copysigntf(CRT_INFINITY, __c) * __a;
COMPLEXTF_IMAGINARY(z) = crt_copysigntf(CRT_INFINITY, __c) * __b;
} else if ((crt_isinf(__a) || crt_isinf(__b)) && crt_isfinite(__c) &&
crt_isfinite(__d)) {
__a = crt_copysignl(crt_isinf(__a) ? 1.0 : 0.0, __a);
__b = crt_copysignl(crt_isinf(__b) ? 1.0 : 0.0, __b);
COMPLEX_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
COMPLEX_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
__a = crt_copysigntf(crt_isinf(__a) ? (fp_t)1.0 : (fp_t)0.0, __a);
__b = crt_copysigntf(crt_isinf(__b) ? (fp_t)1.0 : (fp_t)0.0, __b);
COMPLEXTF_REAL(z) = CRT_INFINITY * (__a * __c + __b * __d);
COMPLEXTF_IMAGINARY(z) = CRT_INFINITY * (__b * __c - __a * __d);
} else if (crt_isinf(__logbw) && __logbw > 0.0 && crt_isfinite(__a) &&
crt_isfinite(__b)) {
__c = crt_copysignl(crt_isinf(__c) ? 1.0 : 0.0, __c);
__d = crt_copysignl(crt_isinf(__d) ? 1.0 : 0.0, __d);
COMPLEX_REAL(z) = 0.0 * (__a * __c + __b * __d);
COMPLEX_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
__c = crt_copysigntf(crt_isinf(__c) ? (fp_t)1.0 : (fp_t)0.0, __c);
__d = crt_copysigntf(crt_isinf(__d) ? (fp_t)1.0 : (fp_t)0.0, __d);
COMPLEXTF_REAL(z) = 0.0 * (__a * __c + __b * __d);
COMPLEXTF_IMAGINARY(z) = 0.0 * (__b * __c - __a * __d);
}
}
return z;
}
#endif

View File

@ -14,8 +14,6 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
COMPILER_RT_ABI fp_t __extenddftf2(double a) {
return __extendXfYf2__(a);
}
COMPILER_RT_ABI dst_t __extenddftf2(src_t a) { return __extendXfYf2__(a); }
#endif

View File

@ -15,8 +15,6 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
COMPILER_RT_ABI long double __extendhftf2(_Float16 a) {
return __extendXfYf2__(a);
}
COMPILER_RT_ABI dst_t __extendhftf2(src_t a) { return __extendXfYf2__(a); }
#endif

View File

@ -14,8 +14,6 @@
#define DST_QUAD
#include "fp_extend_impl.inc"
COMPILER_RT_ABI fp_t __extendsftf2(float a) {
return __extendXfYf2__(a);
}
COMPILER_RT_ABI dst_t __extendsftf2(src_t a) { return __extendXfYf2__(a); }
#endif

View File

@ -9,14 +9,15 @@
// Assumption: long double is a IEEE 80 bit floating point type padded to 128
// bits.
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
#define QUAD_PRECISION
#include "fp_lib.h"
#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
#define SRC_80
#define DST_QUAD
#include "fp_extend_impl.inc"
COMPILER_RT_ABI __float128 __extendxftf2(long double a) {
COMPILER_RT_ABI tf_float __extendxftf2(long double a) {
return __extendXfYf2__(a);
}

View File

@ -102,13 +102,7 @@ static const int dstSigFracBits = 52;
static const int dstExpBits = 11;
#elif defined DST_QUAD
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
#if __LDBL_MANT_DIG__ == 113
typedef long double dst_t;
#elif defined(__x86_64__) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
typedef __float128 dst_t;
#endif
typedef tf_float dst_t;
typedef __uint128_t dst_rep_t;
#define DST_REP_C (__uint128_t)
static const int dstBits = sizeof(dst_t) * CHAR_BIT;

View File

@ -105,18 +105,11 @@ static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
COMPILER_RT_ABI fp_t __adddf3(fp_t a, fp_t b);
#elif defined QUAD_PRECISION
#if __LDBL_MANT_DIG__ == 113 && defined(__SIZEOF_INT128__)
// TODO: Availability of the *tf functions should not depend on long double
// being IEEE 128, but instead on being able to use a 128-bit floating-point
// type, which includes __float128.
// Right now this (incorrectly) stops the builtins from being used for x86.
#define CRT_LDBL_128BIT
#define CRT_HAS_TF_MODE
#define TF_C(c) c##L
#if defined(CRT_HAS_TF_MODE)
typedef uint64_t half_rep_t;
typedef __uint128_t rep_t;
typedef __int128_t srep_t;
typedef long double fp_t;
typedef tf_float fp_t;
#define HALF_REP_C UINT64_C
#define REP_C (__uint128_t)
// Note: Since there is no explicit way to tell compiler the constant is a
@ -207,13 +200,13 @@ static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
#undef Word_HiMask
#undef Word_LoMask
#undef Word_FullMask
#endif // __LDBL_MANT_DIG__ == 113 && __SIZEOF_INT128__
#endif // defined(CRT_HAS_TF_MODE)
#else
#error SINGLE_PRECISION, DOUBLE_PRECISION or QUAD_PRECISION must be defined.
#endif
#if defined(SINGLE_PRECISION) || defined(DOUBLE_PRECISION) || \
defined(CRT_LDBL_128BIT)
(defined(QUAD_PRECISION) && defined(CRT_HAS_TF_MODE))
#define typeWidth (sizeof(rep_t) * CHAR_BIT)
#define exponentBits (typeWidth - significandBits - 1)
#define maxExponent ((1 << exponentBits) - 1)
@ -393,31 +386,40 @@ static __inline fp_t __compiler_rt_fmax(fp_t x, fp_t y) {
#endif
}
#elif defined(QUAD_PRECISION)
#if defined(CRT_LDBL_128BIT)
static __inline fp_t __compiler_rt_logbl(fp_t x) {
return __compiler_rt_logbX(x);
}
static __inline fp_t __compiler_rt_scalbnl(fp_t x, int y) {
return __compiler_rt_scalbnX(x, y);
}
static __inline fp_t __compiler_rt_fmaxl(fp_t x, fp_t y) {
return __compiler_rt_fmaxX(x, y);
}
#else
#elif defined(QUAD_PRECISION) && defined(CRT_HAS_TF_MODE)
// The generic implementation only works for ieee754 floating point. For other
// floating point types, continue to rely on the libm implementation for now.
static __inline long double __compiler_rt_logbl(long double x) {
#if defined(CRT_HAS_IEEE_TF)
static __inline tf_float __compiler_rt_logbtf(tf_float x) {
return __compiler_rt_logbX(x);
}
static __inline tf_float __compiler_rt_scalbntf(tf_float x, int y) {
return __compiler_rt_scalbnX(x, y);
}
static __inline tf_float __compiler_rt_fmaxtf(tf_float x, tf_float y) {
return __compiler_rt_fmaxX(x, y);
}
#define __compiler_rt_logbl __compiler_rt_logbtf
#define __compiler_rt_scalbnl __compiler_rt_scalbntf
#define __compiler_rt_fmaxl __compiler_rt_fmaxtf
#define crt_fabstf crt_fabsf128
#define crt_copysigntf crt_copysignf128
#elif defined(CRT_LDBL_128BIT)
static __inline tf_float __compiler_rt_logbtf(tf_float x) {
return crt_logbl(x);
}
static __inline long double __compiler_rt_scalbnl(long double x, int y) {
static __inline tf_float __compiler_rt_scalbntf(tf_float x, int y) {
return crt_scalbnl(x, y);
}
static __inline long double __compiler_rt_fmaxl(long double x, long double y) {
static __inline tf_float __compiler_rt_fmaxtf(tf_float x, tf_float y) {
return crt_fmaxl(x, y);
}
#endif // CRT_LDBL_128BIT
#define __compiler_rt_logbl crt_logbl
#define __compiler_rt_scalbnl crt_scalbnl
#define __compiler_rt_fmaxl crt_fmaxl
#else
#error Unsupported TF mode type
#endif
#endif // *_PRECISION

View File

@ -36,13 +36,7 @@ static const int srcSigFracBits = 52;
static const int srcExpBits = 11;
#elif defined SRC_QUAD
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
#if __LDBL_MANT_DIG__ == 113
typedef long double src_t;
#elif defined(__x86_64__) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
typedef __float128 src_t;
#endif
typedef tf_float src_t;
typedef __uint128_t src_rep_t;
#define SRC_REP_C (__uint128_t)
static const int srcBits = sizeof(src_t) * CHAR_BIT;

View File

@ -65,6 +65,11 @@
#define crt_copysign(x, y) __builtin_copysign((x), (y))
#define crt_copysignf(x, y) __builtin_copysignf((x), (y))
#define crt_copysignl(x, y) __builtin_copysignl((x), (y))
#if __has_builtin(__builtin_copysignf128)
#define crt_copysignf128(x, y) __builtin_copysignf128((x), (y))
#elif __has_builtin(__builtin_copysignq) || (defined(__GNUC__) && __GNUC__ >= 7)
#define crt_copysignf128(x, y) __builtin_copysignq((x), (y))
#endif
#endif
#if defined(_MSC_VER) && !defined(__clang__)
@ -75,6 +80,11 @@
#define crt_fabs(x) __builtin_fabs((x))
#define crt_fabsf(x) __builtin_fabsf((x))
#define crt_fabsl(x) __builtin_fabsl((x))
#if __has_builtin(__builtin_fabsf128)
#define crt_fabsf128(x) __builtin_fabsf128((x))
#elif __has_builtin(__builtin_fabsq) || (defined(__GNUC__) && __GNUC__ >= 7)
#define crt_fabsf128(x) __builtin_fabsq((x))
#endif
#endif
#if defined(_MSC_VER) && !defined(__clang__)

View File

@ -59,7 +59,7 @@ enum {
};
#elif defined DST_QUAD
typedef long double dst_t;
typedef tf_float dst_t;
typedef __uint128_t dst_rep_t;
#define DST_REP_C (__uint128_t)

View File

@ -165,6 +165,53 @@ typedef struct {
#define HAS_80_BIT_LONG_DOUBLE 0
#endif
#ifdef __powerpc64__
// From https://gcc.gnu.org/wiki/Ieee128PowerPC:
// PowerPC64 uses the following suffixes:
// IFmode: IBM extended double
// KFmode: IEEE 128-bit floating point
// TFmode: Matches the default for long double. With -mabi=ieeelongdouble,
// it is IEEE 128-bit, with -mabi=ibmlongdouble IBM extended double
// Since compiler-rt only implements the tf set of libcalls, we use long double
// for the tf_float typedef.
typedef long double tf_float;
#define CRT_LDBL_128BIT
#define CRT_HAS_F128
#if __LDBL_MANT_DIG__ == 113 && !defined(__LONG_DOUBLE_IBM128__)
#define CRT_HAS_IEEE_TF
#define CRT_LDBL_IEEE_F128
#endif
#define TF_C(x) x##L
#elif __LDBL_MANT_DIG__ == 113
// Use long double instead of __float128 if it matches the IEEE 128-bit format.
#define CRT_LDBL_128BIT
#define CRT_HAS_F128
#define CRT_HAS_IEEE_TF
#define CRT_LDBL_IEEE_F128
typedef long double tf_float;
#define TF_C(x) x##L
#elif defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
#define CRT_HAS___FLOAT128_KEYWORD
#define CRT_HAS_F128
// NB: we assume the __float128 type uses IEEE representation.
#define CRT_HAS_IEEE_TF
typedef __float128 tf_float;
#define TF_C(x) x##Q
#endif
#ifdef CRT_HAS_F128
typedef union {
uqwords u;
tf_float f;
} tf_bits;
#endif
// __(u)int128_t is currently needed to compile the *tf builtins as we would
// otherwise need to manually expand the bit manipulation on two 64-bit value.
#if defined(CRT_HAS_128BIT) && defined(CRT_HAS_F128)
#define CRT_HAS_TF_MODE
#endif
#if CRT_HAS_FLOATING_POINT
typedef union {
uqwords u;
@ -175,6 +222,20 @@ typedef union {
typedef float _Complex Fcomplex;
typedef double _Complex Dcomplex;
typedef long double _Complex Lcomplex;
#if defined(CRT_LDBL_128BIT)
typedef Lcomplex Qcomplex;
#define CRT_HAS_NATIVE_COMPLEX_F128
#elif defined(CRT_HAS___FLOAT128_KEYWORD)
#if defined(__clang_major__) && __clang_major__ > 10
// Clang prior to 11 did not support __float128 _Complex.
typedef __float128 _Complex Qcomplex;
#define CRT_HAS_NATIVE_COMPLEX_F128
#elif defined(__GNUC__) && __GNUC__ >= 7
// GCC does not allow __float128 _Complex, but accepts _Float128 _Complex.
typedef _Float128 _Complex Qcomplex;
#define CRT_HAS_NATIVE_COMPLEX_F128
#endif
#endif
#define COMPLEX_REAL(x) __real__(x)
#define COMPLEX_IMAGINARY(x) __imag__(x)
@ -194,5 +255,17 @@ typedef struct {
#define COMPLEX_REAL(x) (x).real
#define COMPLEX_IMAGINARY(x) (x).imaginary
#endif
#ifdef CRT_HAS_NATIVE_COMPLEX_F128
#define COMPLEXTF_REAL(x) __real__(x)
#define COMPLEXTF_IMAGINARY(x) __imag__(x)
#elif defined(CRT_HAS_F128)
typedef struct {
tf_float real, imaginary;
} Qcomplex;
#define COMPLEXTF_REAL(x) (x).real
#define COMPLEXTF_IMAGINARY(x) (x).imaginary
#endif
#endif
#endif // INT_TYPES_H

View File

@ -10,56 +10,61 @@
//
//===----------------------------------------------------------------------===//
#define QUAD_PRECISION
#include "fp_lib.h"
#include "int_lib.h"
#include "int_math.h"
#if defined(CRT_HAS_TF_MODE)
// Returns: the product of a + ib and c + id
COMPILER_RT_ABI long double _Complex __multc3(long double a, long double b,
long double c, long double d) {
long double ac = a * c;
long double bd = b * d;
long double ad = a * d;
long double bc = b * c;
long double _Complex z;
__real__ z = ac - bd;
__imag__ z = ad + bc;
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z)) {
COMPILER_RT_ABI Qcomplex __multc3(fp_t a, fp_t b, fp_t c, fp_t d) {
fp_t ac = a * c;
fp_t bd = b * d;
fp_t ad = a * d;
fp_t bc = b * c;
Qcomplex z;
COMPLEXTF_REAL(z) = ac - bd;
COMPLEXTF_IMAGINARY(z) = ad + bc;
if (crt_isnan(COMPLEXTF_REAL(z)) && crt_isnan(COMPLEXTF_IMAGINARY(z))) {
int recalc = 0;
if (crt_isinf(a) || crt_isinf(b)) {
a = crt_copysignl(crt_isinf(a) ? 1 : 0, a);
b = crt_copysignl(crt_isinf(b) ? 1 : 0, b);
a = crt_copysigntf(crt_isinf(a) ? 1 : 0, a);
b = crt_copysigntf(crt_isinf(b) ? 1 : 0, b);
if (crt_isnan(c))
c = crt_copysignl(0, c);
c = crt_copysigntf(0, c);
if (crt_isnan(d))
d = crt_copysignl(0, d);
d = crt_copysigntf(0, d);
recalc = 1;
}
if (crt_isinf(c) || crt_isinf(d)) {
c = crt_copysignl(crt_isinf(c) ? 1 : 0, c);
d = crt_copysignl(crt_isinf(d) ? 1 : 0, d);
c = crt_copysigntf(crt_isinf(c) ? 1 : 0, c);
d = crt_copysigntf(crt_isinf(d) ? 1 : 0, d);
if (crt_isnan(a))
a = crt_copysignl(0, a);
a = crt_copysigntf(0, a);
if (crt_isnan(b))
b = crt_copysignl(0, b);
b = crt_copysigntf(0, b);
recalc = 1;
}
if (!recalc &&
(crt_isinf(ac) || crt_isinf(bd) || crt_isinf(ad) || crt_isinf(bc))) {
if (crt_isnan(a))
a = crt_copysignl(0, a);
a = crt_copysigntf(0, a);
if (crt_isnan(b))
b = crt_copysignl(0, b);
b = crt_copysigntf(0, b);
if (crt_isnan(c))
c = crt_copysignl(0, c);
c = crt_copysigntf(0, c);
if (crt_isnan(d))
d = crt_copysignl(0, d);
d = crt_copysigntf(0, d);
recalc = 1;
}
if (recalc) {
__real__ z = CRT_INFINITY * (a * c - b * d);
__imag__ z = CRT_INFINITY * (a * d + b * c);
COMPLEXTF_REAL(z) = CRT_INFINITY * (a * c - b * d);
COMPLEXTF_IMAGINARY(z) = CRT_INFINITY * (a * d + b * c);
}
}
return z;
}
#endif

View File

@ -17,9 +17,9 @@
// Returns: a ^ b
COMPILER_RT_ABI long double __powitf2(long double a, int b) {
COMPILER_RT_ABI fp_t __powitf2(fp_t a, int b) {
const int recip = b < 0;
long double r = 1;
fp_t r = 1;
while (1) {
if (b & 1)
r *= a;

View File

@ -14,6 +14,6 @@
#define DST_DOUBLE
#include "fp_trunc_impl.inc"
COMPILER_RT_ABI double __trunctfdf2(long double a) { return __truncXfYf2__(a); }
COMPILER_RT_ABI dst_t __trunctfdf2(src_t a) { return __truncXfYf2__(a); }
#endif

View File

@ -15,8 +15,6 @@
#define DST_HALF
#include "fp_trunc_impl.inc"
COMPILER_RT_ABI _Float16 __trunctfhf2(long double a) {
return __truncXfYf2__(a);
}
COMPILER_RT_ABI dst_t __trunctfhf2(src_t a) { return __truncXfYf2__(a); }
#endif

View File

@ -14,6 +14,6 @@
#define DST_SINGLE
#include "fp_trunc_impl.inc"
COMPILER_RT_ABI float __trunctfsf2(long double a) { return __truncXfYf2__(a); }
COMPILER_RT_ABI dst_t __trunctfsf2(src_t a) { return __truncXfYf2__(a); }
#endif

View File

@ -9,15 +9,16 @@
// Assumption: long double is a IEEE 80 bit floating point type padded to 128
// bits.
// TODO: use fp_lib.h once QUAD_PRECISION is available on x86_64.
#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__))
#define QUAD_PRECISION
#include "fp_lib.h"
#if defined(CRT_HAS_TF_MODE) && __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
#define SRC_QUAD
#define DST_80
#include "fp_trunc_impl.inc"
COMPILER_RT_ABI long double __trunctfxf2(__float128 a) {
COMPILER_RT_ABI long double __trunctfxf2(tf_float a) {
return __truncXfYf2__(a);
}

View File

@ -4,102 +4,90 @@
#include <fenv.h>
#include <stdio.h>
#if __LDBL_MANT_DIG__ == 113
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
#include "int_lib.h"
#include "fp_test.h"
# include "fp_test.h"
# include "int_lib.h"
// Returns: a + b
COMPILER_RT_ABI long double __addtf3(long double a, long double b);
COMPILER_RT_ABI tf_float __addtf3(tf_float a, tf_float b);
int test__addtf3(long double a, long double b,
uint64_t expectedHi, uint64_t expectedLo)
{
long double x = __addtf3(a, b);
int ret = compareResultF128(x, expectedHi, expectedLo);
int test__addtf3(tf_float a, tf_float b, uint64_t expectedHi,
uint64_t expectedLo) {
tf_float x = __addtf3(a, b);
int ret = compareResultF128(x, expectedHi, expectedLo);
if (ret){
printf("error in test__addtf3(%.20Lf, %.20Lf) = %.20Lf, "
"expected %.20Lf\n", a, b, x,
fromRep128(expectedHi, expectedLo));
}
if (ret) {
printf("error in test__addtf3(%.20Lf, %.20Lf) = %.20Lf, "
"expected %.20Lf\n",
a, b, x, fromRep128(expectedHi, expectedLo));
}
return ret;
return ret;
}
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0};
#endif
int main()
{
#if __LDBL_MANT_DIG__ == 113
// qNaN + any = qNaN
if (test__addtf3(makeQNaN128(),
0x1.23456789abcdefp+5L,
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// NaN + any = NaN
if (test__addtf3(makeNaN128(UINT64_C(0x800030000000)),
0x1.23456789abcdefp+5L,
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// inf + inf = inf
if (test__addtf3(makeInf128(),
makeInf128(),
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// inf + any = inf
if (test__addtf3(makeInf128(),
0x1.2335653452436234723489432abcdefp+5L,
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// any + any
if (test__addtf3(0x1.23456734245345543849abcdefp+5L,
0x1.edcba52449872455634654321fp-1L,
UINT64_C(0x40042afc95c8b579),
UINT64_C(0x61e58dd6c51eb77c)))
return 1;
int main() {
#if defined(CRT_HAS_IEEE_TF)
// qNaN + any = qNaN
if (test__addtf3(makeQNaN128(), 0x1.23456789abcdefp+5L,
UINT64_C(0x7fff800000000000), UINT64_C(0x0)))
return 1;
// NaN + any = NaN
if (test__addtf3(makeNaN128(UINT64_C(0x800030000000)),
TF_C(0x1.23456789abcdefp+5), UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// inf + inf = inf
if (test__addtf3(makeInf128(), makeInf128(), UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// inf + any = inf
if (test__addtf3(makeInf128(), TF_C(0x1.2335653452436234723489432abcdefp+5),
UINT64_C(0x7fff000000000000), UINT64_C(0x0)))
return 1;
// any + any
if (test__addtf3(TF_C(0x1.23456734245345543849abcdefp+5),
TF_C(0x1.edcba52449872455634654321fp-1),
UINT64_C(0x40042afc95c8b579), UINT64_C(0x61e58dd6c51eb77c)))
return 1;
#if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \
defined(i386) || defined(__x86_64__) || (defined(__loongarch__) && \
__loongarch_frlen != 0)
// Rounding mode tests on supported architectures
const long double m = 1234.0L, n = 0.01L;
# if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \
defined(i386) || defined(__x86_64__) || \
(defined(__loongarch__) && __loongarch_frlen != 0)
// Rounding mode tests on supported architectures
const tf_float m = 1234.0L, n = 0.01L;
fesetround(FE_UPWARD);
if (test__addtf3(m, n,
UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d8)))
return 1;
fesetround(FE_UPWARD);
if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d8)))
return 1;
fesetround(FE_DOWNWARD);
if (test__addtf3(m, n,
UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d7)))
return 1;
fesetround(FE_DOWNWARD);
if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d7)))
return 1;
fesetround(FE_TOWARDZERO);
if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d7)))
return 1;
fesetround(FE_TOWARDZERO);
if (test__addtf3(m, n,
UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d7)))
return 1;
fesetround(FE_TONEAREST);
if (test__addtf3(m, n,
UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d7)))
return 1;
#endif
fesetround(FE_TONEAREST);
if (test__addtf3(m, n, UINT64_C(0x40093480a3d70a3d),
UINT64_C(0x70a3d70a3d70a3d7)))
return 1;
# endif
#else
printf("skipped\n");
printf("skipped\n");
#endif
return 0;
return 0;
}

View File

@ -6,7 +6,10 @@
#include <stdio.h>
#include "fp_lib.h"
#if defined(CRT_HAS_TF_MODE)
// Since we are comparing the compiler-rt IEEE implementation against libc's
// long double implementation, this test can only succeed if long double
// is an IEEE 128-bit floating point number.
#if defined(CRT_HAS_TF_MODE) && defined(CRT_LDBL_IEEE_F128)
int test__compiler_rt_fmaxl(fp_t x, fp_t y) {
fp_t crt_value = __compiler_rt_fmaxl(x, y);
@ -40,10 +43,7 @@ fp_t cases[] = {
-1.001, 1.001, -1.002, 1.002,
};
#endif
int main() {
#if defined(CRT_HAS_TF_MODE)
const unsigned N = sizeof(cases) / sizeof(cases[0]);
unsigned i, j;
for (i = 0; i < N; ++i) {
@ -51,8 +51,11 @@ int main() {
if (test__compiler_rt_fmaxl(cases[i], cases[j])) return 1;
}
}
#else
printf("skipped\n");
#endif
return 0;
}
#else
int main() {
printf("skipped\n");
return 0;
}
#endif

View File

@ -1,18 +1,18 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
#define QUAD_PRECISION
#include <math.h>
#include <stdio.h>
#include "fp_lib.h"
#include "int_lib.h"
#include <math.h>
#include <stdio.h>
#if defined(CRT_HAS_TF_MODE)
int test__compiler_rt_logbl(fp_t x) {
#if defined(__ve__)
# if defined(__ve__)
if (fpclassify(x) == FP_SUBNORMAL)
return 0;
#endif
# endif
fp_t crt_value = __compiler_rt_logbl(x);
fp_t libm_value = logbl(x);
// Compare the values, considering all NaNs equivalent, as the spec doesn't
@ -24,49 +24,62 @@ int test__compiler_rt_logbl(fp_t x) {
x_t.all = toRep(x);
crt_value_t.all = toRep(crt_value);
libm_value_t.all = toRep(libm_value);
printf(
"error: in __compiler_rt_logbl([%llX %llX]) = [%llX %llX] != "
"[%llX %llX]\n",
x_t.s.high, x_t.s.low, crt_value_t.s.high, crt_value_t.s.low,
libm_value_t.s.high, libm_value_t.s.low);
printf("error: in __compiler_rt_logbl([%llX %llX]) = [%llX %llX] != "
"[%llX %llX]\n",
x_t.s.high, x_t.s.low, crt_value_t.s.high, crt_value_t.s.low,
libm_value_t.s.high, libm_value_t.s.low);
return 1;
}
return 0;
}
double cases[] = {
fp_t cases[] = {
1.e-6, -1.e-6, NAN, -NAN, INFINITY, -INFINITY, -1,
-0.0, 0.0, 1, -2, 2, -0.5, 0.5,
};
#endif
int main() {
#if defined(CRT_HAS_TF_MODE)
const unsigned N = sizeof(cases) / sizeof(cases[0]);
unsigned i;
for (i = 0; i < N; ++i) {
if (test__compiler_rt_logbl(cases[i])) return 1;
for (unsigned i = 0; i < N; ++i) {
if (test__compiler_rt_logbl(cases[i]))
return 1;
}
// Test a moving 1 bit, especially to handle denormal values.
// Test the negation as well.
// Since we are comparing the compiler-rt IEEE implementation against libc's
// long double implementation, this test can only succeed if long double
// is an IEEE 128-bit floating point number (otherwise we will see mismatches
// once we reach numbers that cannot be precisely represented in long double
// format).
# if defined(CRT_LDBL_IEEE_F128)
rep_t x = signBit;
int i = 0;
while (x) {
if (test__compiler_rt_logbl(fromRep(x))) return 1;
if (test__compiler_rt_logbl(fromRep(signBit ^ x))) return 1;
if (test__compiler_rt_logbl(fromRep(x)))
return 1;
if (test__compiler_rt_logbl(fromRep(signBit ^ x)))
return 1;
x >>= 1;
printf("l1: %d\n", i++);
}
// Also try a couple moving ones
x = signBit | (signBit >> 1) | (signBit >> 2);
while (x) {
if (test__compiler_rt_logbl(fromRep(x))) return 1;
if (test__compiler_rt_logbl(fromRep(signBit ^ x))) return 1;
if (test__compiler_rt_logbl(fromRep(x)))
return 1;
if (test__compiler_rt_logbl(fromRep(signBit ^ x)))
return 1;
x >>= 1;
printf("l1: %d\n", i++);
}
#else
printf("skipped\n");
#endif
return 0;
}
#else
int main() {
printf("skipped\n");
return 0;
}
#endif

View File

@ -1,12 +1,12 @@
// RUN: %clang_builtins %s %librt -o %t && %run %t
#define QUAD_PRECISION
#include "fp_lib.h"
#include <fenv.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include "fp_lib.h"
#if defined(CRT_HAS_TF_MODE)
@ -14,7 +14,7 @@ int test__compiler_rt_scalbnl(const char *mode, fp_t x, int y) {
#if defined(__ve__)
if (fpclassify(x) == FP_SUBNORMAL)
return 0;
#endif
# endif
fp_t crt_value = __compiler_rt_scalbnl(x, y);
fp_t libm_value = scalbnl(x, y);
// Consider +/-0 unequal, but disregard the sign/payload of NaN.
@ -39,13 +39,34 @@ int test__compiler_rt_scalbnl(const char *mode, fp_t x, int y) {
}
fp_t cases[] = {
-NAN, NAN, -INFINITY, INFINITY, -0.0, 0.0, -1, 1, -2, 2,
LDBL_TRUE_MIN, LDBL_MIN, LDBL_MAX,
-1.001, 1.001, -1.002, 1.002, 1.e-6, -1.e-6,
0x1.0p-16381L,
0x1.0p-16382L,
0x1.0p-16383L, // subnormal
0x1.0p-16384L, // subnormal
-NAN,
NAN,
-INFINITY,
INFINITY,
-0.0,
0.0,
-1,
1,
-2,
2,
// Since we are comparing the compiler-rt IEEE implementation against libc's
// long double implementation, this test can only succeed if long double
// is an IEEE 128-bit floating point number.
# if defined(CRT_LDBL_IEEE_F128)
LDBL_TRUE_MIN,
# endif
LDBL_MIN,
LDBL_MAX,
-1.001,
1.001,
-1.002,
1.002,
1.e-6,
-1.e-6,
TF_C(0x1.0p-16381),
TF_C(0x1.0p-16382),
TF_C(0x1.0p-16383), // subnormal
TF_C(0x1.0p-16384), // subnormal
};
int iterate_cases(const char *mode) {
@ -54,28 +75,35 @@ int iterate_cases(const char *mode) {
for (i = 0; i < N; ++i) {
int j;
for (j = -5; j <= 5; ++j) {
if (test__compiler_rt_scalbnl(mode, cases[i], j)) return 1;
printf("%d, %d\n", i, j);
if (test__compiler_rt_scalbnl(mode, cases[i], j))
return 1;
}
if (test__compiler_rt_scalbnl(mode, cases[i], -100000)) return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], 100000)) return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], INT_MIN)) return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], INT_MAX)) return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], -100000))
return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], 100000))
return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], INT_MIN))
return 1;
if (test__compiler_rt_scalbnl(mode, cases[i], INT_MAX))
return 1;
}
return 0;
}
#endif
int main() {
#if defined(CRT_HAS_TF_MODE)
if (iterate_cases("default")) return 1;
if (iterate_cases("default"))
return 1;
// Skip rounding mode tests (fesetround) because compiler-rt's quad-precision
// multiply also ignores the current rounding mode.
#else
printf("skipped\n");
#endif
return 0;
}
#else
int main() {
printf("skipped\n");
return 0;
}
#endif

View File

@ -9,362 +9,357 @@
#include <stdio.h>
#include "int_lib.h"
#include <math.h>
#include "int_math.h"
#include <complex.h>
#include <math.h>
// Returns: the quotient of (a + ib) / (c + id)
COMPILER_RT_ABI long double _Complex
__divtc3(long double __a, long double __b, long double __c, long double __d);
COMPILER_RT_ABI Qcomplex __divtc3(tf_float __a, tf_float __b, tf_float __c,
tf_float __d);
enum {zero, non_zero, inf, NaN, non_zero_nan};
int
classify(long double _Complex x)
{
if (x == 0)
return zero;
if (isinf(creall(x)) || isinf(cimagl(x)))
return inf;
if (isnan(creall(x)) && isnan(cimagl(x)))
return NaN;
if (isnan(creall(x)))
{
if (cimagl(x) == 0)
return NaN;
return non_zero_nan;
}
if (isnan(cimagl(x)))
{
if (creall(x) == 0)
return NaN;
return non_zero_nan;
}
return non_zero;
static int classify(Qcomplex x) {
tf_float real = COMPLEXTF_REAL(x);
tf_float imag = COMPLEXTF_IMAGINARY(x);
if (real == 0.0 && imag == 0.0)
return zero;
if (crt_isinf(real) || crt_isinf(imag))
return inf;
if (crt_isnan(real) && crt_isnan(imag))
return NaN;
if (crt_isnan(real)) {
if (imag == 0.0)
return NaN;
return non_zero_nan;
}
if (crt_isnan(imag)) {
if (real == 0.0)
return NaN;
return non_zero_nan;
}
return non_zero;
}
int test__divtc3(long double a, long double b, long double c, long double d)
{
long double _Complex r = __divtc3(a, b, c, d);
// printf("test__divtc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n",
// a, b, c, d, creall(r), cimagl(r));
long double _Complex dividend;
long double _Complex divisor;
__real__ dividend = a;
__imag__ dividend = b;
__real__ divisor = c;
__imag__ divisor = d;
switch (classify(dividend))
{
static int test__divtc3(tf_float a, tf_float b, tf_float c, tf_float d) {
Qcomplex r = __divtc3(a, b, c, d);
Qcomplex dividend;
Qcomplex divisor;
COMPLEXTF_REAL(dividend) = a;
COMPLEXTF_IMAGINARY(dividend) = b;
COMPLEXTF_REAL(divisor) = c;
COMPLEXTF_IMAGINARY(divisor) = d;
switch (classify(dividend)) {
case zero:
switch (classify(divisor)) {
case zero:
switch (classify(divisor))
{
case zero:
if (classify(r) != NaN)
return 1;
break;
case non_zero:
if (classify(r) != zero)
return 1;
break;
case inf:
if (classify(r) != zero)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
if (classify(r) != NaN)
return 1;
break;
case non_zero:
switch (classify(divisor))
{
case zero:
if (classify(r) != inf)
return 1;
break;
case non_zero:
if (classify(r) != non_zero)
return 1;
{
long double _Complex z = (a * c + b * d) / (c * c + d * d)
+ (b * c - a * d) / (c * c + d * d) * _Complex_I;
if (cabsl((r - z)/r) > 1.e-6)
return 1;
}
break;
case inf:
if (classify(r) != zero)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
if (classify(r) != zero)
return 1;
break;
case inf:
switch (classify(divisor))
{
case zero:
if (classify(r) != inf)
return 1;
break;
case non_zero:
if (classify(r) != inf)
return 1;
break;
case inf:
if (classify(r) != NaN)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
if (classify(r) != zero)
return 1;
break;
case NaN:
switch (classify(divisor))
{
case zero:
if (classify(r) != NaN)
return 1;
break;
case non_zero:
if (classify(r) != NaN)
return 1;
break;
case inf:
if (classify(r) != NaN)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
switch (classify(divisor))
{
case zero:
if (classify(r) != inf)
return 1;
break;
case non_zero:
if (classify(r) != NaN)
return 1;
break;
case inf:
if (classify(r) != NaN)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
if (classify(r) != NaN)
return 1;
break;
}
return 0;
break;
case non_zero:
switch (classify(divisor)) {
case zero:
if (classify(r) != inf)
return 1;
break;
case non_zero:
if (classify(r) != non_zero)
return 1;
{
tf_float zReal = (a * c + b * d) / (c * c + d * d);
tf_float zImag = (b * c - a * d) / (c * c + d * d);
Qcomplex diff =
__divtc3(COMPLEXTF_REAL(r) - zReal, COMPLEXTF_IMAGINARY(r) - zImag,
COMPLEXTF_REAL(r), COMPLEXTF_IMAGINARY(r));
// cabsl(z) == hypotl(creall(z), cimagl(z))
#ifdef CRT_LDBL_128BIT
if (hypotl(COMPLEXTF_REAL(diff), COMPLEXTF_IMAGINARY(diff)) > 1.e-6)
#else
// Avoid dependency on __trunctfxf2 for ld80 platforms and use double instead.
if (hypot(COMPLEXTF_REAL(diff), COMPLEXTF_IMAGINARY(diff)) > 1.e-6)
#endif
return 1;
}
break;
case inf:
if (classify(r) != zero)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
case inf:
switch (classify(divisor)) {
case zero:
if (classify(r) != inf)
return 1;
break;
case non_zero:
if (classify(r) != inf)
return 1;
break;
case inf:
if (classify(r) != NaN)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
case NaN:
switch (classify(divisor)) {
case zero:
if (classify(r) != NaN)
return 1;
break;
case non_zero:
if (classify(r) != NaN)
return 1;
break;
case inf:
if (classify(r) != NaN)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
case non_zero_nan:
switch (classify(divisor)) {
case zero:
if (classify(r) != inf)
return 1;
break;
case non_zero:
if (classify(r) != NaN)
return 1;
break;
case inf:
if (classify(r) != NaN)
return 1;
break;
case NaN:
if (classify(r) != NaN)
return 1;
break;
case non_zero_nan:
if (classify(r) != NaN)
return 1;
break;
}
break;
}
return 0;
}
long double x[][2] =
{
{ 1.e-6, 1.e-6},
{-1.e-6, 1.e-6},
{-1.e-6, -1.e-6},
{ 1.e-6, -1.e-6},
tf_float x[][2] = {{1.e-6, 1.e-6},
{-1.e-6, 1.e-6},
{-1.e-6, -1.e-6},
{1.e-6, -1.e-6},
{ 1.e+6, 1.e-6},
{-1.e+6, 1.e-6},
{-1.e+6, -1.e-6},
{ 1.e+6, -1.e-6},
{1.e+6, 1.e-6},
{-1.e+6, 1.e-6},
{-1.e+6, -1.e-6},
{1.e+6, -1.e-6},
{ 1.e-6, 1.e+6},
{-1.e-6, 1.e+6},
{-1.e-6, -1.e+6},
{ 1.e-6, -1.e+6},
{1.e-6, 1.e+6},
{-1.e-6, 1.e+6},
{-1.e-6, -1.e+6},
{1.e-6, -1.e+6},
{ 1.e+6, 1.e+6},
{-1.e+6, 1.e+6},
{-1.e+6, -1.e+6},
{ 1.e+6, -1.e+6},
{1.e+6, 1.e+6},
{-1.e+6, 1.e+6},
{-1.e+6, -1.e+6},
{1.e+6, -1.e+6},
{NAN, NAN},
{-INFINITY, NAN},
{-2, NAN},
{-1, NAN},
{-0.5, NAN},
{-0., NAN},
{+0., NAN},
{0.5, NAN},
{1, NAN},
{2, NAN},
{INFINITY, NAN},
{NAN, NAN},
{-INFINITY, NAN},
{-2, NAN},
{-1, NAN},
{-0.5, NAN},
{-0., NAN},
{+0., NAN},
{0.5, NAN},
{1, NAN},
{2, NAN},
{INFINITY, NAN},
{NAN, -INFINITY},
{-INFINITY, -INFINITY},
{-2, -INFINITY},
{-1, -INFINITY},
{-0.5, -INFINITY},
{-0., -INFINITY},
{+0., -INFINITY},
{0.5, -INFINITY},
{1, -INFINITY},
{2, -INFINITY},
{INFINITY, -INFINITY},
{NAN, -INFINITY},
{-INFINITY, -INFINITY},
{-2, -INFINITY},
{-1, -INFINITY},
{-0.5, -INFINITY},
{-0., -INFINITY},
{+0., -INFINITY},
{0.5, -INFINITY},
{1, -INFINITY},
{2, -INFINITY},
{INFINITY, -INFINITY},
{NAN, -2},
{-INFINITY, -2},
{-2, -2},
{-1, -2},
{-0.5, -2},
{-0., -2},
{+0., -2},
{0.5, -2},
{1, -2},
{2, -2},
{INFINITY, -2},
{NAN, -2},
{-INFINITY, -2},
{-2, -2},
{-1, -2},
{-0.5, -2},
{-0., -2},
{+0., -2},
{0.5, -2},
{1, -2},
{2, -2},
{INFINITY, -2},
{NAN, -1},
{-INFINITY, -1},
{-2, -1},
{-1, -1},
{-0.5, -1},
{-0., -1},
{+0., -1},
{0.5, -1},
{1, -1},
{2, -1},
{INFINITY, -1},
{NAN, -1},
{-INFINITY, -1},
{-2, -1},
{-1, -1},
{-0.5, -1},
{-0., -1},
{+0., -1},
{0.5, -1},
{1, -1},
{2, -1},
{INFINITY, -1},
{NAN, -0.5},
{-INFINITY, -0.5},
{-2, -0.5},
{-1, -0.5},
{-0.5, -0.5},
{-0., -0.5},
{+0., -0.5},
{0.5, -0.5},
{1, -0.5},
{2, -0.5},
{INFINITY, -0.5},
{NAN, -0.5},
{-INFINITY, -0.5},
{-2, -0.5},
{-1, -0.5},
{-0.5, -0.5},
{-0., -0.5},
{+0., -0.5},
{0.5, -0.5},
{1, -0.5},
{2, -0.5},
{INFINITY, -0.5},
{NAN, -0.},
{-INFINITY, -0.},
{-2, -0.},
{-1, -0.},
{-0.5, -0.},
{-0., -0.},
{+0., -0.},
{0.5, -0.},
{1, -0.},
{2, -0.},
{INFINITY, -0.},
{NAN, -0.},
{-INFINITY, -0.},
{-2, -0.},
{-1, -0.},
{-0.5, -0.},
{-0., -0.},
{+0., -0.},
{0.5, -0.},
{1, -0.},
{2, -0.},
{INFINITY, -0.},
{NAN, 0.},
{-INFINITY, 0.},
{-2, 0.},
{-1, 0.},
{-0.5, 0.},
{-0., 0.},
{+0., 0.},
{0.5, 0.},
{1, 0.},
{2, 0.},
{INFINITY, 0.},
{NAN, 0.},
{-INFINITY, 0.},
{-2, 0.},
{-1, 0.},
{-0.5, 0.},
{-0., 0.},
{+0., 0.},
{0.5, 0.},
{1, 0.},
{2, 0.},
{INFINITY, 0.},
{NAN, 0.5},
{-INFINITY, 0.5},
{-2, 0.5},
{-1, 0.5},
{-0.5, 0.5},
{-0., 0.5},
{+0., 0.5},
{0.5, 0.5},
{1, 0.5},
{2, 0.5},
{INFINITY, 0.5},
{NAN, 0.5},
{-INFINITY, 0.5},
{-2, 0.5},
{-1, 0.5},
{-0.5, 0.5},
{-0., 0.5},
{+0., 0.5},
{0.5, 0.5},
{1, 0.5},
{2, 0.5},
{INFINITY, 0.5},
{NAN, 1},
{-INFINITY, 1},
{-2, 1},
{-1, 1},
{-0.5, 1},
{-0., 1},
{+0., 1},
{0.5, 1},
{1, 1},
{2, 1},
{INFINITY, 1},
{NAN, 1},
{-INFINITY, 1},
{-2, 1},
{-1, 1},
{-0.5, 1},
{-0., 1},
{+0., 1},
{0.5, 1},
{1, 1},
{2, 1},
{INFINITY, 1},
{NAN, 2},
{-INFINITY, 2},
{-2, 2},
{-1, 2},
{-0.5, 2},
{-0., 2},
{+0., 2},
{0.5, 2},
{1, 2},
{2, 2},
{INFINITY, 2},
{NAN, 2},
{-INFINITY, 2},
{-2, 2},
{-1, 2},
{-0.5, 2},
{-0., 2},
{+0., 2},
{0.5, 2},
{1, 2},
{2, 2},
{INFINITY, 2},
{NAN, INFINITY},
{-INFINITY, INFINITY},
{-2, INFINITY},
{-1, INFINITY},
{-0.5, INFINITY},
{-0., INFINITY},
{+0., INFINITY},
{0.5, INFINITY},
{1, INFINITY},
{2, INFINITY},
{INFINITY, INFINITY}
{NAN, INFINITY},
{-INFINITY, INFINITY},
{-2, INFINITY},
{-1, INFINITY},
{-0.5, INFINITY},
{-0., INFINITY},
{+0., INFINITY},
{0.5, INFINITY},
{1, INFINITY},
{2, INFINITY},
{INFINITY, INFINITY}
};
int main()
{
const unsigned N = sizeof(x) / sizeof(x[0]);
unsigned i, j;
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (test__divtc3(x[i][0], x[i][1], x[j][0], x[j][1]))
return 1;
}
int main() {
const unsigned N = sizeof(x) / sizeof(x[0]);
unsigned i, j;
for (i = 0; i < N; ++i) {
for (j = 0; j < N; ++j) {
if (test__divtc3(x[i][0], x[i][1], x[j][0], x[j][1])) {
fprintf(stderr, "Failed for %g, %g, %g, %g\n", (double)x[i][0],
(double)x[i][1], (double)x[j][0], (double)x[j][1]);
return 1;
}
}
}
// printf("No errors found.\n");
return 0;
fprintf(stderr, "No errors found.\n");
return 0;
}

View File

@ -4,190 +4,161 @@
#include "int_lib.h"
#include <stdio.h>
#if __LDBL_MANT_DIG__ == 113
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
#include "fp_test.h"
# include "fp_test.h"
// Returns: a / b
COMPILER_RT_ABI long double __divtf3(long double a, long double b);
COMPILER_RT_ABI tf_float __divtf3(tf_float a, tf_float b);
int test__divtf3(long double a, long double b,
uint64_t expectedHi, uint64_t expectedLo)
{
long double x = __divtf3(a, b);
int ret = compareResultF128(x, expectedHi, expectedLo);
int test__divtf3(tf_float a, tf_float b, uint64_t expectedHi,
uint64_t expectedLo) {
tf_float x = __divtf3(a, b);
int ret = compareResultF128(x, expectedHi, expectedLo);
if (ret){
printf("error in test__divtf3(%.20Le, %.20Le) = %.20Le, "
"expected %.20Le\n", a, b, x,
fromRep128(expectedHi, expectedLo));
}
return ret;
if (ret) {
printf("error in test__divtf3(%.20Le, %.20Le) = %.20Le, "
"expected %.20Le\n",
a, b, x, fromRep128(expectedHi, expectedLo));
}
return ret;
}
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0};
#endif
int main()
{
#if __LDBL_MANT_DIG__ == 113
// Returned NaNs are assumed to be qNaN by default
int main() {
#if defined(CRT_HAS_IEEE_TF)
// Returned NaNs are assumed to be qNaN by default
// qNaN / any = qNaN
if (test__divtf3(makeQNaN128(),
0x1.23456789abcdefp+5L,
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// NaN / any = NaN
if (test__divtf3(makeNaN128(UINT64_C(0x30000000)),
0x1.23456789abcdefp+5L,
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// any / qNaN = qNaN
if (test__divtf3(0x1.23456789abcdefp+5L,
makeQNaN128(),
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// any / NaN = NaN
if (test__divtf3(0x1.23456789abcdefp+5L,
makeNaN128(UINT64_C(0x30000000)),
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// qNaN / any = qNaN
if (test__divtf3(makeQNaN128(), TF_C(0x1.23456789abcdefp+5),
UINT64_C(0x7fff800000000000), UINT64_C(0x0)))
return 1;
// NaN / any = NaN
if (test__divtf3(makeNaN128(UINT64_C(0x30000000)),
TF_C(0x1.23456789abcdefp+5), UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// any / qNaN = qNaN
if (test__divtf3(TF_C(0x1.23456789abcdefp+5), makeQNaN128(),
UINT64_C(0x7fff800000000000), UINT64_C(0x0)))
return 1;
// any / NaN = NaN
if (test__divtf3(TF_C(0x1.23456789abcdefp+5),
makeNaN128(UINT64_C(0x30000000)),
UINT64_C(0x7fff800000000000), UINT64_C(0x0)))
return 1;
// +Inf / positive = +Inf
if (test__divtf3(makeInf128(), 3.L,
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// +Inf / negative = -Inf
if (test__divtf3(makeInf128(), -3.L,
UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// -Inf / positive = -Inf
if (test__divtf3(makeNegativeInf128(), 3.L,
UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// -Inf / negative = +Inf
if (test__divtf3(makeNegativeInf128(), -3.L,
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// +Inf / positive = +Inf
if (test__divtf3(makeInf128(), TF_C(3.), UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// +Inf / negative = -Inf
if (test__divtf3(makeInf128(), -TF_C(3.), UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// -Inf / positive = -Inf
if (test__divtf3(makeNegativeInf128(), TF_C(3.), UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// -Inf / negative = +Inf
if (test__divtf3(makeNegativeInf128(), -TF_C(3.),
UINT64_C(0x7fff000000000000), UINT64_C(0x0)))
return 1;
// Inf / Inf = NaN
if (test__divtf3(makeInf128(), makeInf128(),
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// 0.0 / 0.0 = NaN
if (test__divtf3(+0x0.0p+0L, +0x0.0p+0L,
UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// +0.0 / +Inf = +0.0
if (test__divtf3(+0x0.0p+0L, makeInf128(),
UINT64_C(0x0),
UINT64_C(0x0)))
return 1;
// +Inf / +0.0 = +Inf
if (test__divtf3(makeInf128(), +0x0.0p+0L,
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// Inf / Inf = NaN
if (test__divtf3(makeInf128(), makeInf128(), UINT64_C(0x7fff800000000000),
UINT64_C(0x0)))
return 1;
// 0.0 / 0.0 = NaN
if (test__divtf3(+TF_C(0x0.0p+0), +TF_C(0x0.0p+0),
UINT64_C(0x7fff800000000000), UINT64_C(0x0)))
return 1;
// +0.0 / +Inf = +0.0
if (test__divtf3(+TF_C(0x0.0p+0), makeInf128(), UINT64_C(0x0), UINT64_C(0x0)))
return 1;
// +Inf / +0.0 = +Inf
if (test__divtf3(makeInf128(), +TF_C(0x0.0p+0), UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// positive / +0.0 = +Inf
if (test__divtf3(+1.0L, +0x0.0p+0L,
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// positive / -0.0 = -Inf
if (test__divtf3(+1.0L, -0x0.0p+0L,
UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// negative / +0.0 = -Inf
if (test__divtf3(-1.0L, +0x0.0p+0L,
UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// negative / -0.0 = +Inf
if (test__divtf3(-1.0L, -0x0.0p+0L,
UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// positive / +0.0 = +Inf
if (test__divtf3(+TF_C(1.0), +TF_C(0x0.0p+0), UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// positive / -0.0 = -Inf
if (test__divtf3(+1.0L, -TF_C(0x0.0p+0), UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// negative / +0.0 = -Inf
if (test__divtf3(-1.0L, +TF_C(0x0.0p+0), UINT64_C(0xffff000000000000),
UINT64_C(0x0)))
return 1;
// negative / -0.0 = +Inf
if (test__divtf3(TF_C(-1.0), -TF_C(0x0.0p+0), UINT64_C(0x7fff000000000000),
UINT64_C(0x0)))
return 1;
// 1/3
if (test__divtf3(1.L, 3.L,
UINT64_C(0x3ffd555555555555),
UINT64_C(0x5555555555555555)))
return 1;
// smallest normal result
if (test__divtf3(0x1.0p-16381L, 2.L,
UINT64_C(0x0001000000000000),
UINT64_C(0x0)))
return 1;
// 1/3
if (test__divtf3(TF_C(1.), TF_C(3.), UINT64_C(0x3ffd555555555555),
UINT64_C(0x5555555555555555)))
return 1;
// smallest normal result
if (test__divtf3(TF_C(0x1.0p-16381), TF_C(2.), UINT64_C(0x0001000000000000),
UINT64_C(0x0)))
return 1;
// divisor is exactly 1.0
if (test__divtf3(0x1.0p+0L,
0x1.0p+0L,
UINT64_C(0x3fff000000000000),
UINT64_C(0x0)))
return 1;
// divisor is truncated to exactly 1.0 in UQ1.63
if (test__divtf3(0x1.0p+0L,
0x1.0000000000000001p+0L,
UINT64_C(0x3ffeffffffffffff),
UINT64_C(0xfffe000000000000)))
return 1;
// divisor is exactly 1.0
if (test__divtf3(TF_C(0x1.0p+0), TF_C(0x1.0p+0), UINT64_C(0x3fff000000000000),
UINT64_C(0x0)))
return 1;
// divisor is truncated to exactly 1.0 in UQ1.63
if (test__divtf3(TF_C(0x1.0p+0), TF_C(0x1.0000000000000001p+0),
UINT64_C(0x3ffeffffffffffff), UINT64_C(0xfffe000000000000)))
return 1;
// smallest normal value divided by 2.0
if (test__divtf3(0x1.0p-16382L, 2.L, UINT64_C(0x0000800000000000), UINT64_C(0x0)))
return 1;
// smallest subnormal result
if (test__divtf3(0x1.0p-16382L, 0x1p+112L, UINT64_C(0x0), UINT64_C(0x1)))
return 1;
// smallest normal value divided by 2.0
if (test__divtf3(TF_C(0x1.0p-16382), 2.L, UINT64_C(0x0000800000000000),
UINT64_C(0x0)))
return 1;
// smallest subnormal result
if (test__divtf3(TF_C(0x1.0p-16382), TF_C(0x1p+112), UINT64_C(0x0),
UINT64_C(0x1)))
return 1;
// any / any
if (test__divtf3(0x1.a23b45362464523375893ab4cdefp+5L,
0x1.eedcbaba3a94546558237654321fp-1L,
UINT64_C(0x4004b0b72924d407),
UINT64_C(0x0717e84356c6eba2)))
return 1;
if (test__divtf3(0x1.a2b34c56d745382f9abf2c3dfeffp-50L,
0x1.ed2c3ba15935332532287654321fp-9L,
UINT64_C(0x3fd5b2af3f828c9b),
UINT64_C(0x40e51f64cde8b1f2)))
return 15;
if (test__divtf3(0x1.2345f6aaaa786555f42432abcdefp+456L,
0x1.edacbba9874f765463544dd3621fp+6400L,
UINT64_C(0x28c62e15dc464466),
UINT64_C(0xb5a07586348557ac)))
return 1;
if (test__divtf3(0x1.2d3456f789ba6322bc665544edefp-234L,
0x1.eddcdba39f3c8b7a36564354321fp-4455L,
UINT64_C(0x507b38442b539266),
UINT64_C(0x22ce0f1d024e1252)))
return 1;
if (test__divtf3(0x1.2345f6b77b7a8953365433abcdefp+234L,
0x1.edcba987d6bb3aa467754354321fp-4055L,
UINT64_C(0x50bf2e02f0798d36),
UINT64_C(0x5e6fcb6b60044078)))
return 1;
if (test__divtf3(6.72420628622418701252535563464350521E-4932L,
2.L,
UINT64_C(0x0001000000000000),
UINT64_C(0)))
return 1;
// any / any
if (test__divtf3(TF_C(0x1.a23b45362464523375893ab4cdefp+5),
TF_C(0x1.eedcbaba3a94546558237654321fp-1),
UINT64_C(0x4004b0b72924d407), UINT64_C(0x0717e84356c6eba2)))
return 1;
if (test__divtf3(TF_C(0x1.a2b34c56d745382f9abf2c3dfeffp-50),
TF_C(0x1.ed2c3ba15935332532287654321fp-9),
UINT64_C(0x3fd5b2af3f828c9b), UINT64_C(0x40e51f64cde8b1f2)))
return 15;
if (test__divtf3(TF_C(0x1.2345f6aaaa786555f42432abcdefp+456),
TF_C(0x1.edacbba9874f765463544dd3621fp+6400),
UINT64_C(0x28c62e15dc464466), UINT64_C(0xb5a07586348557ac)))
return 1;
if (test__divtf3(TF_C(0x1.2d3456f789ba6322bc665544edefp-234),
TF_C(0x1.eddcdba39f3c8b7a36564354321fp-4455),
UINT64_C(0x507b38442b539266), UINT64_C(0x22ce0f1d024e1252)))
return 1;
if (test__divtf3(TF_C(0x1.2345f6b77b7a8953365433abcdefp+234),
TF_C(0x1.edcba987d6bb3aa467754354321fp-4055),
UINT64_C(0x50bf2e02f0798d36), UINT64_C(0x5e6fcb6b60044078)))
return 1;
if (test__divtf3(TF_C(6.72420628622418701252535563464350521E-4932), TF_C(2.),
UINT64_C(0x0001000000000000), UINT64_C(0)))
return 1;
#else
printf("skipped\n");
printf("skipped\n");
#endif
return 0;
return 0;
}

View File

@ -9,10 +9,10 @@
#include "fp_test.h"
COMPILER_RT_ABI __float128 __extendxftf2(long double a);
COMPILER_RT_ABI tf_float __extendxftf2(long double a);
int test__extendxftf2(long double a, uint64_t expectedHi, uint64_t expectedLo) {
__float128 x = __extendxftf2(a);
tf_float x = __extendxftf2(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
if (ret) {

View File

@ -2,58 +2,66 @@
// REQUIRES: librt_has_floatditf
#include "int_lib.h"
#include <math.h>
#include <complex.h>
#include <math.h>
#include <stdio.h>
#if __LDBL_MANT_DIG__ == 113
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
#include "fp_test.h"
# include "fp_test.h"
// Returns: long integer converted to long double
// Returns: long integer converted to tf_float
COMPILER_RT_ABI long double __floatditf(di_int a);
COMPILER_RT_ABI tf_float __floatditf(di_int a);
int test__floatditf(di_int a, uint64_t expectedHi, uint64_t expectedLo)
{
long double x = __floatditf(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
int test__floatditf(di_int a, uint64_t expectedHi, uint64_t expectedLo) {
tf_float x = __floatditf(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
if (ret)
printf("error in __floatditf(%Ld) = %.20Lf, "
"expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo));
return ret;
if (ret)
printf("error in __floatditf(%Ld) = %.20Lf, "
"expected %.20Lf\n",
a, x, fromRep128(expectedHi, expectedLo));
return ret;
}
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
#endif
int main()
{
#if __LDBL_MANT_DIG__ == 113
if (test__floatditf(0x7fffffffffffffff, UINT64_C(0x403dffffffffffff), UINT64_C(0xfffc000000000000)))
return 1;
if (test__floatditf(0x123456789abcdef1, UINT64_C(0x403b23456789abcd), UINT64_C(0xef10000000000000)))
return 1;
if (test__floatditf(0x2, UINT64_C(0x4000000000000000), UINT64_C(0x0)))
return 1;
if (test__floatditf(0x1, UINT64_C(0x3fff000000000000), UINT64_C(0x0)))
return 1;
if (test__floatditf(0x0, UINT64_C(0x0), UINT64_C(0x0)))
return 1;
if (test__floatditf(0xffffffffffffffff, UINT64_C(0xbfff000000000000), UINT64_C(0x0)))
return 1;
if (test__floatditf(0xfffffffffffffffe, UINT64_C(0xc000000000000000), UINT64_C(0x0)))
return 1;
if (test__floatditf(-0x123456789abcdef1, UINT64_C(0xc03b23456789abcd), UINT64_C(0xef10000000000000)))
return 1;
if (test__floatditf(0x8000000000000000, UINT64_C(0xc03e000000000000), UINT64_C(0x0)))
return 1;
int main() {
#if defined(CRT_HAS_IEEE_TF)
if (test__floatditf(0x7fffffffffffffff, UINT64_C(0x403dffffffffffff),
UINT64_C(0xfffc000000000000)))
return 1;
if (test__floatditf(0x123456789abcdef1, UINT64_C(0x403b23456789abcd),
UINT64_C(0xef10000000000000)))
return 1;
if (test__floatditf(0x2, UINT64_C(0x4000000000000000), UINT64_C(0x0)))
return 1;
if (test__floatditf(0x1, UINT64_C(0x3fff000000000000), UINT64_C(0x0)))
return 1;
if (test__floatditf(0x0, UINT64_C(0x0), UINT64_C(0x0)))
return 1;
if (test__floatditf(0xffffffffffffffff, UINT64_C(0xbfff000000000000),
UINT64_C(0x0)))
return 1;
if (test__floatditf(0xfffffffffffffffe, UINT64_C(0xc000000000000000),
UINT64_C(0x0)))
return 1;
if (test__floatditf(-0x123456789abcdef1, UINT64_C(0xc03b23456789abcd),
UINT64_C(0xef10000000000000)))
return 1;
if (test__floatditf(0x8000000000000000, UINT64_C(0xc03e000000000000),
UINT64_C(0x0)))
return 1;
#else
printf("skipped\n");
printf("skipped\n");
#endif
return 0;
return 0;
}

View File

@ -7,7 +7,12 @@
#include <float.h>
#include <stdio.h>
#if defined(CRT_HAS_TF_MODE)
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
# include "fp_test.h"
/* Returns: convert a ti_int to a fp_t, rounding toward even. */
@ -21,93 +26,97 @@
COMPILER_RT_ABI fp_t __floattitf(ti_int a);
int test__floattitf(ti_int a, fp_t expected) {
int _test__floattitf(int line, ti_int a, fp_t expected) {
fp_t x = __floattitf(a);
if (x != expected) {
twords at;
at.all = a;
printf("error in __floattitf(0x%.16llX%.16llX) = %LA, expected %LA\n",
at.s.high, at.s.low, x, expected);
__uint128_t expected_rep = toRep128(expected);
__uint128_t res_rep = toRep128(x);
printf("%s:%d: error in __floattitf(0x%.16llX%.16llX) = "
"0x%.16llX%.16llX, expected 0x%.16llX%.16llX\n",
__FILE__, line, at.s.high, at.s.low, (uint64_t)(res_rep >> 64),
(uint64_t)res_rep, (uint64_t)(expected_rep >> 64),
(uint64_t)expected_rep);
}
return x != expected;
}
# define test__floattitf(a, e) _test__floattitf(__LINE__, a, e)
char assumption_1[sizeof(ti_int) == 2 * sizeof(di_int)] = {0};
char assumption_2[sizeof(ti_int) * CHAR_BIT == 128] = {0};
char assumption_3[sizeof(fp_t) * CHAR_BIT == 128] = {0};
#endif
int main() {
#if defined(CRT_HAS_TF_MODE)
if (test__floattitf(0, 0.0))
if (test__floattitf(0, TF_C(0.0)))
return 1;
if (test__floattitf(1, 1.0))
if (test__floattitf(1, TF_C(1.0)))
return 1;
if (test__floattitf(2, 2.0))
if (test__floattitf(2, TF_C(2.0)))
return 1;
if (test__floattitf(20, 20.0))
if (test__floattitf(20, TF_C(20.0)))
return 1;
if (test__floattitf(-1, -1.0))
if (test__floattitf(-1, -TF_C(1.0)))
return 1;
if (test__floattitf(-2, -2.0))
if (test__floattitf(-2, -TF_C(2.0)))
return 1;
if (test__floattitf(-20, -20.0))
if (test__floattitf(-20, -TF_C(20.0)))
return 1;
if (test__floattitf(0x7FFFFF8000000000LL, 0x1.FFFFFEp+62))
if (test__floattitf(0x7FFFFF8000000000LL, TF_C(0x1.FFFFFEp+62)))
return 1;
if (test__floattitf(0x7FFFFFFFFFFFF800LL, 0x1.FFFFFFFFFFFFEp+62))
if (test__floattitf(0x7FFFFFFFFFFFF800LL, TF_C(0x1.FFFFFFFFFFFFEp+62)))
return 1;
if (test__floattitf(0x7FFFFF0000000000LL, 0x1.FFFFFCp+62))
if (test__floattitf(0x7FFFFF0000000000LL, TF_C(0x1.FFFFFCp+62)))
return 1;
if (test__floattitf(0x7FFFFFFFFFFFF000LL, 0x1.FFFFFFFFFFFFCp+62))
if (test__floattitf(0x7FFFFFFFFFFFF000LL, TF_C(0x1.FFFFFFFFFFFFCp+62)))
return 1;
if (test__floattitf(make_ti(0x8000008000000000LL, 0), -0x1.FFFFFEp+126))
if (test__floattitf(make_ti(0x8000008000000000LL, 0), -TF_C(0x1.FFFFFEp+126)))
return 1;
if (test__floattitf(make_ti(0x8000000000000800LL, 0),
-0x1.FFFFFFFFFFFFEp+126))
-TF_C(0x1.FFFFFFFFFFFFEp+126)))
return 1;
if (test__floattitf(make_ti(0x8000010000000000LL, 0), -0x1.FFFFFCp+126))
if (test__floattitf(make_ti(0x8000010000000000LL, 0), -TF_C(0x1.FFFFFCp+126)))
return 1;
if (test__floattitf(make_ti(0x8000000000001000LL, 0),
-0x1.FFFFFFFFFFFFCp+126))
-TF_C(0x1.FFFFFFFFFFFFCp+126)))
return 1;
if (test__floattitf(make_ti(0x8000000000000000LL, 0), -0x1.000000p+127))
if (test__floattitf(make_ti(0x8000000000000000LL, 0), -TF_C(0x1.000000p+127)))
return 1;
if (test__floattitf(make_ti(0x8000000000000001LL, 0),
-TF_C(0x1.FFFFFFFFFFFFFFFCp+126)))
return 1;
if (test__floattitf(0x0007FB72E8000000LL, 0x1.FEDCBAp+50))
if (test__floattitf(0x0007FB72E8000000LL, TF_C(0x1.FEDCBAp+50)))
return 1;
if (test__floattitf(0x0007FB72EA000000LL, 0x1.FEDCBA8p+50))
if (test__floattitf(0x0007FB72EA000000LL, TF_C(0x1.FEDCBA8p+50)))
return 1;
if (test__floattitf(0x0007FB72EB000000LL, 0x1.FEDCBACp+50))
if (test__floattitf(0x0007FB72EB000000LL, TF_C(0x1.FEDCBACp+50)))
return 1;
if (test__floattitf(0x0007FB72EBFFFFFFLL, 0x1.FEDCBAFFFFFFCp+50))
if (test__floattitf(0x0007FB72EBFFFFFFLL, TF_C(0x1.FEDCBAFFFFFFCp+50)))
return 1;
if (test__floattitf(0x0007FB72EC000000LL, 0x1.FEDCBBp+50))
if (test__floattitf(0x0007FB72EC000000LL, TF_C(0x1.FEDCBBp+50)))
return 1;
if (test__floattitf(0x0007FB72E8000001LL, 0x1.FEDCBA0000004p+50))
if (test__floattitf(0x0007FB72E8000001LL, TF_C(0x1.FEDCBA0000004p+50)))
return 1;
if (test__floattitf(0x0007FB72E6000000LL, 0x1.FEDCB98p+50))
if (test__floattitf(0x0007FB72E6000000LL, TF_C(0x1.FEDCB98p+50)))
return 1;
if (test__floattitf(0x0007FB72E7000000LL, 0x1.FEDCB9Cp+50))
if (test__floattitf(0x0007FB72E7000000LL, TF_C(0x1.FEDCB9Cp+50)))
return 1;
if (test__floattitf(0x0007FB72E7FFFFFFLL, 0x1.FEDCB9FFFFFFCp+50))
if (test__floattitf(0x0007FB72E7FFFFFFLL, TF_C(0x1.FEDCB9FFFFFFCp+50)))
return 1;
if (test__floattitf(0x0007FB72E4000001LL, 0x1.FEDCB90000004p+50))
if (test__floattitf(0x0007FB72E4000001LL, TF_C(0x1.FEDCB90000004p+50)))
return 1;
if (test__floattitf(0x0007FB72E4000000LL, 0x1.FEDCB9p+50))
if (test__floattitf(0x0007FB72E4000000LL, TF_C(0x1.FEDCB9p+50)))
return 1;
if (test__floattitf(0x023479FD0E092DC0LL, 0x1.1A3CFE870496Ep+57))
if (test__floattitf(0x023479FD0E092DC0LL, TF_C(0x1.1A3CFE870496Ep+57)))
return 1;
if (test__floattitf(0x023479FD0E092DA1LL, TF_C(0x1.1A3CFE870496D08p+57)))
return 1;
@ -135,7 +144,7 @@ int main() {
return 1;
if (test__floattitf(0x023479FD0E092DDFLL, TF_C(0x1.1A3CFE870496EF8p+57)))
return 1;
if (test__floattitf(0x023479FD0E092DE0LL, 0x1.1A3CFE870496Fp+57))
if (test__floattitf(0x023479FD0E092DE0LL, TF_C(0x1.1A3CFE870496Fp+57)))
return 1;
if (test__floattitf(make_ti(0x023479FD0E092DC0LL, 0),
@ -215,8 +224,12 @@ int main() {
if (test__floattitf(make_ti(0x123456789ABCDEF0LL, 0x123456789ABC57FFLL),
TF_C(0x1.23456789ABCDEF0123456789ABC5p+124)))
return 1;
#else
printf("skipped\n");
#endif
return 0;
}
#else
int main() {
printf("skipped\n");
return 0;
}
#endif

View File

@ -2,56 +2,63 @@
// REQUIRES: librt_has_floatunditf
#include "int_lib.h"
#include <math.h>
#include <complex.h>
#include <math.h>
#include <stdio.h>
#if __LDBL_MANT_DIG__ == 113
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
#include "fp_test.h"
# include "fp_test.h"
// Returns: long integer converted to long double
COMPILER_RT_ABI long double __floatunditf(du_int a);
COMPILER_RT_ABI tf_float __floatunditf(du_int a);
int test__floatunditf(du_int a, uint64_t expectedHi, uint64_t expectedLo)
{
long double x = __floatunditf(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
int test__floatunditf(du_int a, uint64_t expectedHi, uint64_t expectedLo) {
tf_float x = __floatunditf(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
if (ret)
printf("error in __floatunditf(%Lu) = %.20Lf, "
"expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo));
return ret;
if (ret)
printf("error in __floatunditf(%Lu) = %.20Lf, "
"expected %.20Lf\n",
a, x, fromRep128(expectedHi, expectedLo));
return ret;
}
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
#endif
int main()
{
#if __LDBL_MANT_DIG__ == 113
if (test__floatunditf(0xffffffffffffffffULL, UINT64_C(0x403effffffffffff), UINT64_C(0xfffe000000000000)))
return 1;
if (test__floatunditf(0xfffffffffffffffeULL, UINT64_C(0x403effffffffffff), UINT64_C(0xfffc000000000000)))
return 1;
if (test__floatunditf(0x8000000000000000ULL, UINT64_C(0x403e000000000000), UINT64_C(0x0)))
return 1;
if (test__floatunditf(0x7fffffffffffffffULL, UINT64_C(0x403dffffffffffff), UINT64_C(0xfffc000000000000)))
return 1;
if (test__floatunditf(0x123456789abcdef1ULL, UINT64_C(0x403b23456789abcd), UINT64_C(0xef10000000000000)))
return 1;
if (test__floatunditf(0x2ULL, UINT64_C(0x4000000000000000), UINT64_C(0x0)))
return 1;
if (test__floatunditf(0x1ULL, UINT64_C(0x3fff000000000000), UINT64_C(0x0)))
return 1;
if (test__floatunditf(0x0ULL, UINT64_C(0x0), UINT64_C(0x0)))
return 1;
int main() {
#if defined(CRT_HAS_IEEE_TF)
if (test__floatunditf(0xffffffffffffffffULL, UINT64_C(0x403effffffffffff),
UINT64_C(0xfffe000000000000)))
return 1;
if (test__floatunditf(0xfffffffffffffffeULL, UINT64_C(0x403effffffffffff),
UINT64_C(0xfffc000000000000)))
return 1;
if (test__floatunditf(0x8000000000000000ULL, UINT64_C(0x403e000000000000),
UINT64_C(0x0)))
return 1;
if (test__floatunditf(0x7fffffffffffffffULL, UINT64_C(0x403dffffffffffff),
UINT64_C(0xfffc000000000000)))
return 1;
if (test__floatunditf(0x123456789abcdef1ULL, UINT64_C(0x403b23456789abcd),
UINT64_C(0xef10000000000000)))
return 1;
if (test__floatunditf(0x2ULL, UINT64_C(0x4000000000000000), UINT64_C(0x0)))
return 1;
if (test__floatunditf(0x1ULL, UINT64_C(0x3fff000000000000), UINT64_C(0x0)))
return 1;
if (test__floatunditf(0x0ULL, UINT64_C(0x0), UINT64_C(0x0)))
return 1;
#else
printf("skipped\n");
printf("skipped\n");
#endif
return 0;
return 0;
}

View File

@ -4,43 +4,48 @@
#include "int_lib.h"
#include <stdio.h>
#if __LDBL_MANT_DIG__ == 113
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
#include "fp_test.h"
# include "fp_test.h"
COMPILER_RT_ABI long double __floatunsitf(su_int a);
COMPILER_RT_ABI tf_float __floatunsitf(su_int a);
int test__floatunsitf(su_int a, uint64_t expectedHi, uint64_t expectedLo)
{
long double x = __floatunsitf(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
int test__floatunsitf(su_int a, uint64_t expectedHi, uint64_t expectedLo) {
tf_float x = __floatunsitf(a);
int ret = compareResultF128(x, expectedHi, expectedLo);
if (ret){
printf("error in test__floatunsitf(%u) = %.20Lf, "
"expected %.20Lf\n", a, x, fromRep128(expectedHi, expectedLo));
}
return ret;
if (ret) {
printf("error in test__floatunsitf(%u) = %.20Lf, "
"expected %.20Lf\n",
a, x, fromRep128(expectedHi, expectedLo));
}
return ret;
}
char assumption_1[sizeof(long double) * CHAR_BIT == 128] = {0};
char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0};
#endif
int main()
{
#if __LDBL_MANT_DIG__ == 113
if (test__floatunsitf(0x7fffffff, UINT64_C(0x401dfffffffc0000), UINT64_C(0x0)))
return 1;
if (test__floatunsitf(0, UINT64_C(0x0), UINT64_C(0x0)))
return 1;
if (test__floatunsitf(0xffffffff, UINT64_C(0x401efffffffe0000), UINT64_C(0x0)))
return 1;
if (test__floatunsitf(0x12345678, UINT64_C(0x401b234567800000), UINT64_C(0x0)))
return 1;
int main() {
#if defined(CRT_HAS_IEEE_TF)
if (test__floatunsitf(0x7fffffff, UINT64_C(0x401dfffffffc0000),
UINT64_C(0x0)))
return 1;
if (test__floatunsitf(0, UINT64_C(0x0), UINT64_C(0x0)))
return 1;
if (test__floatunsitf(0xffffffff, UINT64_C(0x401efffffffe0000),
UINT64_C(0x0)))
return 1;
if (test__floatunsitf(0x12345678, UINT64_C(0x401b234567800000),
UINT64_C(0x0)))
return 1;
#else
printf("skipped\n");
printf("skipped\n");
#endif
return 0;
return 0;
}

View File

@ -7,11 +7,16 @@
#include <float.h>
#include <stdio.h>
#if defined(CRT_HAS_TF_MODE)
// The testcase currently assumes IEEE TF format, once that has been
// fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for
// IBM 128 floats as well.
#if defined(CRT_HAS_IEEE_TF)
/* Returns: convert a tu_int to a fp_t, rounding toward even. */
# include "fp_test.h"
/* Assumption: fp_t is a IEEE 128 bit floating point type
/* Returns: convert a tu_int to a tf_float, rounding toward even. */
/* Assumption: tf_float is a IEEE 128 bit floating point type
* tu_int is a 128 bit integral type
*/
@ -19,92 +24,98 @@
* mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm
*/
COMPILER_RT_ABI fp_t __floatuntitf(tu_int a);
COMPILER_RT_ABI tf_float __floatuntitf(tu_int a);
int test__floatuntitf(tu_int a, fp_t expected) {
fp_t x = __floatuntitf(a);
int _test__floatuntitf(int line, tu_int a, tf_float expected) {
tf_float x = __floatuntitf(a);
if (x != expected) {
utwords at;
at.all = a;
printf("error in __floatuntitf(0x%.16llX%.16llX) = %LA, expected %LA\n",
at.s.high, at.s.low, x, expected);
__uint128_t expected_rep = toRep128(expected);
__uint128_t res_rep = toRep128(x);
printf("%s:%d: error in __floatuntitf(0x%.16llX%.16llX) = "
"0x%.16llX%.16llX, expected 0x%.16llX%.16llX\n",
__FILE__, line, at.s.high, at.s.low, (uint64_t)(res_rep >> 64),
(uint64_t)res_rep, (uint64_t)(expected_rep >> 64),
(uint64_t)expected_rep);
}
return x != expected;
}
# define test__floatuntitf(a, e) _test__floatuntitf(__LINE__, a, e)
char assumption_1[sizeof(tu_int) == 2 * sizeof(du_int)] = {0};
char assumption_2[sizeof(tu_int) * CHAR_BIT == 128] = {0};
char assumption_3[sizeof(fp_t) * CHAR_BIT == 128] = {0};
char assumption_3[sizeof(tf_float) * CHAR_BIT == 128] = {0};
#endif
int main() {
#if defined(CRT_HAS_TF_MODE)
if (test__floatuntitf(0, 0.0))
#if defined(CRT_HAS_IEEE_TF)
if (test__floatuntitf(0, TF_C(0.0)))
return 1;
if (test__floatuntitf(1, 1.0))
if (test__floatuntitf(1, TF_C(1.0)))
return 1;
if (test__floatuntitf(2, 2.0))
if (test__floatuntitf(2, TF_C(2.0)))
return 1;
if (test__floatuntitf(20, 20.0))
if (test__floatuntitf(20, TF_C(20.0)))
return 1;
if (test__floatuntitf(0x7FFFFF8000000000ULL, 0x1.FFFFFEp+62))
if (test__floatuntitf(0x7FFFFF8000000000ULL, TF_C(0x1.FFFFFEp+62)))
return 1;
if (test__floatuntitf(0x7FFFFFFFFFFFF800ULL, 0x1.FFFFFFFFFFFFEp+62))
if (test__floatuntitf(0x7FFFFFFFFFFFF800ULL, TF_C(0x1.FFFFFFFFFFFFEp+62)))
return 1;
if (test__floatuntitf(0x7FFFFF0000000000ULL, 0x1.FFFFFCp+62))
if (test__floatuntitf(0x7FFFFF0000000000ULL, TF_C(0x1.FFFFFCp+62)))
return 1;
if (test__floatuntitf(0x7FFFFFFFFFFFF000ULL, 0x1.FFFFFFFFFFFFCp+62))
if (test__floatuntitf(0x7FFFFFFFFFFFF000ULL, TF_C(0x1.FFFFFFFFFFFFCp+62)))
return 1;
if (test__floatuntitf(0x7FFFFFFFFFFFFFFFULL, 0xF.FFFFFFFFFFFFFFEp+59L))
if (test__floatuntitf(0x7FFFFFFFFFFFFFFFULL, TF_C(0xF.FFFFFFFFFFFFFFEp+59)))
return 1;
if (test__floatuntitf(0xFFFFFFFFFFFFFFFEULL, 0xF.FFFFFFFFFFFFFFEp+60L))
if (test__floatuntitf(0xFFFFFFFFFFFFFFFEULL, TF_C(0xF.FFFFFFFFFFFFFFEp+60)))
return 1;
if (test__floatuntitf(0xFFFFFFFFFFFFFFFFULL, 0xF.FFFFFFFFFFFFFFFp+60L))
if (test__floatuntitf(0xFFFFFFFFFFFFFFFFULL, TF_C(0xF.FFFFFFFFFFFFFFFp+60)))
return 1;
if (test__floatuntitf(0x8000008000000000ULL, 0x8.000008p+60))
if (test__floatuntitf(0x8000008000000000ULL, TF_C(0x8.000008p+60)))
return 1;
if (test__floatuntitf(0x8000000000000800ULL, 0x8.0000000000008p+60))
if (test__floatuntitf(0x8000000000000800ULL, TF_C(0x8.0000000000008p+60)))
return 1;
if (test__floatuntitf(0x8000010000000000ULL, 0x8.00001p+60))
if (test__floatuntitf(0x8000010000000000ULL, TF_C(0x8.00001p+60)))
return 1;
if (test__floatuntitf(0x8000000000001000ULL, 0x8.000000000001p+60))
if (test__floatuntitf(0x8000000000001000ULL, TF_C(0x8.000000000001p+60)))
return 1;
if (test__floatuntitf(0x8000000000000000ULL, 0x8p+60))
if (test__floatuntitf(0x8000000000000000ULL, TF_C(0x8p+60)))
return 1;
if (test__floatuntitf(0x8000000000000001ULL, TF_C(0x8.000000000000001p+60)))
return 1;
if (test__floatuntitf(0x0007FB72E8000000LL, 0x1.FEDCBAp+50))
if (test__floatuntitf(0x0007FB72E8000000LL, TF_C(0x1.FEDCBAp+50)))
return 1;
if (test__floatuntitf(0x0007FB72EA000000LL, 0x1.FEDCBA8p+50))
if (test__floatuntitf(0x0007FB72EA000000LL, TF_C(0x1.FEDCBA8p+50)))
return 1;
if (test__floatuntitf(0x0007FB72EB000000LL, 0x1.FEDCBACp+50))
if (test__floatuntitf(0x0007FB72EB000000LL, TF_C(0x1.FEDCBACp+50)))
return 1;
if (test__floatuntitf(0x0007FB72EBFFFFFFLL, 0x1.FEDCBAFFFFFFCp+50))
if (test__floatuntitf(0x0007FB72EBFFFFFFLL, TF_C(0x1.FEDCBAFFFFFFCp+50)))
return 1;
if (test__floatuntitf(0x0007FB72EC000000LL, 0x1.FEDCBBp+50))
if (test__floatuntitf(0x0007FB72EC000000LL, TF_C(0x1.FEDCBBp+50)))
return 1;
if (test__floatuntitf(0x0007FB72E8000001LL, 0x1.FEDCBA0000004p+50))
if (test__floatuntitf(0x0007FB72E8000001LL, TF_C(0x1.FEDCBA0000004p+50)))
return 1;
if (test__floatuntitf(0x0007FB72E6000000LL, 0x1.FEDCB98p+50))
if (test__floatuntitf(0x0007FB72E6000000LL, TF_C(0x1.FEDCB98p+50)))
return 1;
if (test__floatuntitf(0x0007FB72E7000000LL, 0x1.FEDCB9Cp+50))
if (test__floatuntitf(0x0007FB72E7000000LL, TF_C(0x1.FEDCB9Cp+50)))
return 1;
if (test__floatuntitf(0x0007FB72E7FFFFFFLL, 0x1.FEDCB9FFFFFFCp+50))
if (test__floatuntitf(0x0007FB72E7FFFFFFLL, TF_C(0x1.FEDCB9FFFFFFCp+50)))
return 1;
if (test__floatuntitf(0x0007FB72E4000001LL, 0x1.FEDCB90000004p+50))
if (test__floatuntitf(0x0007FB72E4000001LL, TF_C(0x1.FEDCB90000004p+50)))
return 1;
if (test__floatuntitf(0x0007FB72E4000000LL, 0x1.FEDCB9p+50))
if (test__floatuntitf(0x0007FB72E4000000LL, TF_C(0x1.FEDCB9p+50)))
return 1;
if (test__floatuntitf(0x023479FD0E092DC0LL, 0x1.1A3CFE870496Ep+57))
if (test__floatuntitf(0x023479FD0E092DC0LL, TF_C(0x1.1A3CFE870496Ep+57)))
return 1;
if (test__floatuntitf(0x023479FD0E092DA1LL, TF_C(0x1.1A3CFE870496D08p+57)))
return 1;
@ -132,7 +143,7 @@ int main() {
return 1;
if (test__floatuntitf(0x023479FD0E092DDFLL, TF_C(0x1.1A3CFE870496EF8p+57)))
return 1;
if (test__floatuntitf(0x023479FD0E092DE0LL, 0x1.1A3CFE870496Fp+57))
if (test__floatuntitf(0x023479FD0E092DE0LL, TF_C(0x1.1A3CFE870496Fp+57)))
return 1;
if (test__floatuntitf(make_ti(0x023479FD0E092DC0LL, 0),

View File

@ -3,24 +3,14 @@
#include <string.h>
#include <stdint.h>
#include "int_types.h"
#ifdef COMPILER_RT_HAS_FLOAT16
#define TYPE_FP16 _Float16
#else
#define TYPE_FP16 uint16_t
#endif
// TODO: Switch to using fp_lib.h once QUAD_PRECISION is available on x86_64.
#if __LDBL_MANT_DIG__ == 113 || \
((__LDBL_MANT_DIG__ == 64) && defined(__x86_64__) && \
(defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)))
#if __LDBL_MANT_DIG__ == 113
#define TYPE_FP128 long double
#else
#define TYPE_FP128 __float128
#endif
#define TEST_COMPILER_RT_HAS_FLOAT128
#endif
enum EXPECTED_RESULT {
LESS_0, LESS_EQUAL_0, EQUAL_0, GREATER_0, GREATER_EQUAL_0, NEQUAL_0
};
@ -50,10 +40,10 @@ static inline double fromRep64(uint64_t x)
return ret;
}
#ifdef TEST_COMPILER_RT_HAS_FLOAT128
static inline TYPE_FP128 fromRep128(uint64_t hi, uint64_t lo) {
#if defined(CRT_HAS_TF_MODE)
static inline tf_float fromRep128(uint64_t hi, uint64_t lo) {
__uint128_t x = ((__uint128_t)hi << 64) + lo;
TYPE_FP128 ret;
tf_float ret;
memcpy(&ret, &x, 16);
return ret;
}
@ -84,8 +74,8 @@ static inline uint64_t toRep64(double x)
return ret;
}
#ifdef TEST_COMPILER_RT_HAS_FLOAT128
static inline __uint128_t toRep128(TYPE_FP128 x) {
#if defined(CRT_HAS_TF_MODE)
static inline __uint128_t toRep128(tf_float x) {
__uint128_t ret;
memcpy(&ret, &x, 16);
return ret;
@ -146,11 +136,11 @@ static inline int compareResultD(double result,
return 1;
}
#ifdef TEST_COMPILER_RT_HAS_FLOAT128
#if defined(CRT_HAS_TF_MODE)
// return 0 if equal
// use two 64-bit integers instead of one 128-bit integer
// because 128-bit integer constant can't be assigned directly
static inline int compareResultF128(TYPE_FP128 result, uint64_t expectedHi,
static inline int compareResultF128(tf_float result, uint64_t expectedHi,
uint64_t expectedLo) {
__uint128_t rep = toRep128(result);
uint64_t hi = rep >> 64;
@ -277,8 +267,8 @@ static inline long double makeInf80(void) {
}
#endif
#ifdef TEST_COMPILER_RT_HAS_FLOAT128
static inline TYPE_FP128 makeQNaN128(void) {
#if defined(CRT_HAS_TF_MODE)
static inline tf_float makeQNaN128(void) {
return fromRep128(0x7fff800000000000UL, 0x0UL);
}
#endif
@ -298,8 +288,8 @@ static inline double makeNaN64(uint64_t rand)
return fromRep64(0x7ff0000000000000UL | (rand & 0xfffffffffffffUL));
}
#ifdef TEST_COMPILER_RT_HAS_FLOAT128
static inline TYPE_FP128 makeNaN128(uint64_t rand) {
#if defined(CRT_HAS_TF_MODE)
static inline tf_float makeNaN128(uint64_t rand) {
return fromRep128(0x7fff000000000000UL | (rand & 0xffffffffffffUL), 0x0UL);
}
#endif
@ -329,12 +319,12 @@ static inline double makeNegativeInf64(void)
return fromRep64(0xfff0000000000000UL);
}
#ifdef TEST_COMPILER_RT_HAS_FLOAT128
static inline TYPE_FP128 makeInf128(void) {
#if defined(CRT_HAS_TF_MODE)
static inline tf_float makeInf128(void) {
return fromRep128(0x7fff000000000000UL, 0x0UL);
}
static inline TYPE_FP128 makeNegativeInf128(void) {
static inline tf_float makeNegativeInf128(void) {
return fromRep128(0xffff000000000000UL, 0x0UL);
}
#endif

View File

@ -9,9 +9,9 @@
#include "fp_test.h"
COMPILER_RT_ABI long double __trunctfxf2(__float128 a);
COMPILER_RT_ABI long double __trunctfxf2(tf_float a);
int test__trunctfxf2(__float128 a, uint64_t expectedHi, uint64_t expectedLo) {
int test__trunctfxf2(tf_float a, uint64_t expectedHi, uint64_t expectedLo) {
long double x = __trunctfxf2(a);
int ret = compareResultF80(x, expectedHi, expectedLo);
;
@ -59,24 +59,24 @@ int main() {
return 1;
// Test rounding near halfway.
__float128 halfwayPlus =
tf_float halfwayPlus =
fromRep128(UINT64_C(0x7ffa000000000000),
((UINT64_C(1) << (112 - 63 - 1)) + UINT64_C(1)));
if (test__trunctfxf2(halfwayPlus, UINT64_C(0x7ffa),
UINT64_C(0x8000000000000001)))
return 1;
__float128 halfwayExactOdd = fromRep128(
tf_float halfwayExactOdd = fromRep128(
UINT64_C(0x7ffa000000000000),
((UINT64_C(1) << (112 - 63)) + (UINT64_C(1) << (112 - 63 - 1))));
if (test__trunctfxf2(halfwayExactOdd, UINT64_C(0x7ffa),
UINT64_C(0x8000000000000002)))
return 1;
__float128 halfwayExactEven =
tf_float halfwayExactEven =
fromRep128(UINT64_C(0x7ffa000000000000), (UINT64_C(1) << (112 - 63 - 1)));
if (test__trunctfxf2(halfwayExactEven, UINT64_C(0x7ffa),
UINT64_C(0x8000000000000000)))
return 1;
__float128 halfwayRoundingWillChangeExponent =
tf_float halfwayRoundingWillChangeExponent =
fromRep128(UINT64_C(0x7ffaffffffffffff), UINT64_C(0xffff000000000001));
if (test__trunctfxf2(halfwayRoundingWillChangeExponent, UINT64_C(0x7ffb),
UINT64_C(0x8000000000000000)))