//===-- mulsc3_test.c - Test __mulsc3 -------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file tests __mulsc3 for the compiler_rt library. // //===----------------------------------------------------------------------===// #include "int_lib.h" #include <math.h> #include <complex.h> #include <stdio.h> // Returns: the product of a + ib and c + id float _Complex __mulsc3(float __a, float __b, float __c, float __d); enum {zero, non_zero, inf, NaN, non_zero_nan}; int classify(float _Complex x) { if (x == 0) return zero; if (isinf(crealf(x)) || isinf(cimagf(x))) return inf; if (isnan(crealf(x)) && isnan(cimagf(x))) return NaN; if (isnan(crealf(x))) { if (cimagf(x) == 0) return NaN; return non_zero_nan; } if (isnan(cimagf(x))) { if (crealf(x) == 0) return NaN; return non_zero_nan; } return non_zero; } int test__mulsc3(float a, float b, float c, float d) { float _Complex r = __mulsc3(a, b, c, d); // printf("test__mulsc3(%f, %f, %f, %f) = %f + I%f\n", // a, b, c, d, crealf(r), cimagf(r)); float _Complex dividend; float _Complex divisor; __real__ dividend = a; __imag__ dividend = b; __real__ divisor = c; __imag__ divisor = d; switch (classify(dividend)) { case zero: switch (classify(divisor)) { case zero: if (classify(r) != zero) return 1; break; case non_zero: if (classify(r) != zero) 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: switch (classify(divisor)) { case zero: if (classify(r) != zero) return 1; break; case non_zero: if (classify(r) != non_zero) return 1; { float _Complex z = a * c - b * d + _Complex_I*(a * d + b * c); // relaxed tolerance to arbitrary (1.e-6) amount. if (cabsf((r-z)/r) > 1.e-6) return 1; } break; case inf: if (classify(r) != inf) 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) != NaN) return 1; break; case non_zero: if (classify(r) != inf) return 1; break; case inf: if (classify(r) != inf) return 1; break; case NaN: if (classify(r) != NaN) return 1; break; case non_zero_nan: if (classify(r) != inf) 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) != NaN) return 1; break; case non_zero: if (classify(r) != NaN) return 1; break; case inf: if (classify(r) != inf) 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; } 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__mulsc3(x[i][0], x[i][1], x[j][0], x[j][1])) return 1; } } return 0; }