// RUN: %clang_builtins %s %librt -lm -o %t && %run %t // REQUIRES: librt_has_divtc3 // REQUIRES: c99-complex // // This test should be XFAILed on 32-bit sparc (sparc-target-arch, Issue // #41838), but that is currently hidden, which caused an XPASS (Issue #72398). // #include #include "int_lib.h" #include "int_math.h" #include #include // Returns: the quotient of (a + ib) / (c + id) #if defined(CRT_HAS_TF_MODE) 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}; 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; } 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: 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; 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; } 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}, {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, -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, -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.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, 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} }; 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; } } } fprintf(stderr, "No errors found.\n"); return 0; } #else int main() { printf("skipped\n"); return 0; } #endif // CRT_HAS_TF_MODE