| 1 | // RUN: %clang_builtins %s %librt -o %t && %run %t |
| 2 | // REQUIRES: librt_has_addtf3 |
| 3 | |
| 4 | #include <fenv.h> |
| 5 | #include <stdio.h> |
| 6 | |
| 7 | #include "fp_test.h" |
| 8 | #include "int_lib.h" |
| 9 | |
| 10 | // The testcase currently assumes IEEE TF format, once that has been |
| 11 | // fixed the defined(CRT_HAS_IEEE_TF) guard can be removed to enable it for |
| 12 | // IBM 128 floats as well. |
| 13 | #if defined(CRT_HAS_IEEE_TF) |
| 14 | |
| 15 | // Returns: a + b |
| 16 | COMPILER_RT_ABI tf_float __addtf3(tf_float a, tf_float b); |
| 17 | |
| 18 | int test__addtf3(tf_float a, tf_float b, uint64_t expectedHi, |
| 19 | uint64_t expectedLo) { |
| 20 | tf_float x = __addtf3(a, b); |
| 21 | int ret = compareResultF128(result: x, expectedHi, expectedLo); |
| 22 | |
| 23 | if (ret) { |
| 24 | printf(format: "error in test__addtf3(%.20Lf, %.20Lf) = %.20Lf, " |
| 25 | "expected %.20Lf\n" , |
| 26 | a, b, x, fromRep128(hi: expectedHi, lo: expectedLo)); |
| 27 | } |
| 28 | |
| 29 | return ret; |
| 30 | } |
| 31 | |
| 32 | char assumption_1[sizeof(tf_float) * CHAR_BIT == 128] = {0}; |
| 33 | |
| 34 | #endif |
| 35 | |
| 36 | int main() { |
| 37 | #if defined(CRT_HAS_IEEE_TF) |
| 38 | // qNaN + any = qNaN |
| 39 | if (test__addtf3(a: makeQNaN128(), b: 0x1.23456789abcdefp+5L, |
| 40 | UINT64_C(0x7fff800000000000), UINT64_C(0x0))) |
| 41 | return 1; |
| 42 | // NaN + any = NaN |
| 43 | if (test__addtf3(a: makeNaN128(UINT64_C(0x800030000000)), |
| 44 | TF_C(0x1.23456789abcdefp+5), UINT64_C(0x7fff800000000000), |
| 45 | UINT64_C(0x0))) |
| 46 | return 1; |
| 47 | // inf + inf = inf |
| 48 | if (test__addtf3(a: makeInf128(), b: makeInf128(), UINT64_C(0x7fff000000000000), |
| 49 | UINT64_C(0x0))) |
| 50 | return 1; |
| 51 | // inf + any = inf |
| 52 | if (test__addtf3(a: makeInf128(), TF_C(0x1.2335653452436234723489432abcdefp+5), |
| 53 | UINT64_C(0x7fff000000000000), UINT64_C(0x0))) |
| 54 | return 1; |
| 55 | // any + any |
| 56 | if (test__addtf3(TF_C(0x1.23456734245345543849abcdefp+5), |
| 57 | TF_C(0x1.edcba52449872455634654321fp-1), |
| 58 | UINT64_C(0x40042afc95c8b579), UINT64_C(0x61e58dd6c51eb77c))) |
| 59 | return 1; |
| 60 | |
| 61 | # if (defined(__arm__) || defined(__aarch64__)) && defined(__ARM_FP) || \ |
| 62 | defined(i386) || defined(__x86_64__) || \ |
| 63 | (defined(__loongarch__) && __loongarch_frlen != 0) |
| 64 | // Rounding mode tests on supported architectures |
| 65 | // Use explicit values because the binary representation of long double |
| 66 | // is platform dependent. Intended values: |
| 67 | // m = 1234.0L, n = 0.01L (where L is a literal for 128 bit long double) |
| 68 | const tf_float m = |
| 69 | fromRep128(UINT64_C(0x4009348000000000), UINT64_C(0x0000000000000000)); |
| 70 | const tf_float n = |
| 71 | fromRep128(UINT64_C(0x3FF847AE147AE147), UINT64_C(0xAE147AE147AE147B)); |
| 72 | |
| 73 | fesetround(FE_UPWARD); |
| 74 | if (test__addtf3(a: m, b: n, UINT64_C(0x40093480a3d70a3d), |
| 75 | UINT64_C(0x70a3d70a3d70a3d8))) |
| 76 | return 1; |
| 77 | |
| 78 | fesetround(FE_DOWNWARD); |
| 79 | if (test__addtf3(a: m, b: n, UINT64_C(0x40093480a3d70a3d), |
| 80 | UINT64_C(0x70a3d70a3d70a3d7))) |
| 81 | return 1; |
| 82 | |
| 83 | fesetround(FE_TOWARDZERO); |
| 84 | if (test__addtf3(a: m, b: n, UINT64_C(0x40093480a3d70a3d), |
| 85 | UINT64_C(0x70a3d70a3d70a3d7))) |
| 86 | return 1; |
| 87 | |
| 88 | fesetround(FE_TONEAREST); |
| 89 | if (test__addtf3(a: m, b: n, UINT64_C(0x40093480a3d70a3d), |
| 90 | UINT64_C(0x70a3d70a3d70a3d7))) |
| 91 | return 1; |
| 92 | # endif |
| 93 | |
| 94 | #else |
| 95 | printf("skipped\n" ); |
| 96 | |
| 97 | #endif |
| 98 | return 0; |
| 99 | } |
| 100 | |