364 lines · c
1// RUN: %clang_builtins %s %librt -lm -o %t && %run %t2// REQUIRES: librt_has_mulsc33// REQUIRES: c99-complex4 5#include "int_lib.h"6#include <math.h>7#include <complex.h>8#include <stdio.h>9 10 11// Returns: the product of a + ib and c + id12 13COMPILER_RT_ABI float _Complex14__mulsc3(float __a, float __b, float __c, float __d);15 16enum {zero, non_zero, inf, NaN, non_zero_nan};17 18int19classify(float _Complex x)20{21 if (x == 0)22 return zero;23 if (isinf(crealf(x)) || isinf(cimagf(x)))24 return inf;25 if (isnan(crealf(x)) && isnan(cimagf(x)))26 return NaN;27 if (isnan(crealf(x)))28 {29 if (cimagf(x) == 0)30 return NaN;31 return non_zero_nan;32 }33 if (isnan(cimagf(x)))34 {35 if (crealf(x) == 0)36 return NaN;37 return non_zero_nan;38 }39 return non_zero;40}41 42int test__mulsc3(float a, float b, float c, float d)43{44 float _Complex r = __mulsc3(a, b, c, d);45// printf("test__mulsc3(%f, %f, %f, %f) = %f + I%f\n",46// a, b, c, d, crealf(r), cimagf(r));47 float _Complex dividend;48 float _Complex divisor;49 50 __real__ dividend = a;51 __imag__ dividend = b;52 __real__ divisor = c;53 __imag__ divisor = d;54 55 switch (classify(dividend))56 {57 case zero:58 switch (classify(divisor))59 {60 case zero:61 if (classify(r) != zero)62 return 1;63 break;64 case non_zero:65 if (classify(r) != zero)66 return 1;67 break;68 case inf:69 if (classify(r) != NaN)70 return 1;71 break;72 case NaN:73 if (classify(r) != NaN)74 return 1;75 break;76 case non_zero_nan:77 if (classify(r) != NaN)78 return 1;79 break;80 }81 break;82 case non_zero:83 switch (classify(divisor))84 {85 case zero:86 if (classify(r) != zero)87 return 1;88 break;89 case non_zero:90 if (classify(r) != non_zero)91 return 1;92 {93 float _Complex z = a * c - b * d + _Complex_I*(a * d + b * c);94 // relaxed tolerance to arbitrary (1.e-6) amount.95 if (cabsf((r-z)/r) > 1.e-6)96 return 1;97 }98 break;99 case inf:100 if (classify(r) != inf)101 return 1;102 break;103 case NaN:104 if (classify(r) != NaN)105 return 1;106 break;107 case non_zero_nan:108 if (classify(r) != NaN)109 return 1;110 break;111 }112 break;113 case inf:114 switch (classify(divisor))115 {116 case zero:117 if (classify(r) != NaN)118 return 1;119 break;120 case non_zero:121 if (classify(r) != inf)122 return 1;123 break;124 case inf:125 if (classify(r) != inf)126 return 1;127 break;128 case NaN:129 if (classify(r) != NaN)130 return 1;131 break;132 case non_zero_nan:133 if (classify(r) != inf)134 return 1;135 break;136 }137 break;138 case NaN:139 switch (classify(divisor))140 {141 case zero:142 if (classify(r) != NaN)143 return 1;144 break;145 case non_zero:146 if (classify(r) != NaN)147 return 1;148 break;149 case inf:150 if (classify(r) != NaN)151 return 1;152 break;153 case NaN:154 if (classify(r) != NaN)155 return 1;156 break;157 case non_zero_nan:158 if (classify(r) != NaN)159 return 1;160 break;161 }162 break;163 case non_zero_nan:164 switch (classify(divisor))165 {166 case zero:167 if (classify(r) != NaN)168 return 1;169 break;170 case non_zero:171 if (classify(r) != NaN)172 return 1;173 break;174 case inf:175 if (classify(r) != inf)176 return 1;177 break;178 case NaN:179 if (classify(r) != NaN)180 return 1;181 break;182 case non_zero_nan:183 if (classify(r) != NaN)184 return 1;185 break;186 }187 break;188 }189 190 return 0;191}192 193float x[][2] =194{195 { 1.e-6, 1.e-6},196 {-1.e-6, 1.e-6},197 {-1.e-6, -1.e-6},198 { 1.e-6, -1.e-6},199 200 { 1.e+6, 1.e-6},201 {-1.e+6, 1.e-6},202 {-1.e+6, -1.e-6},203 { 1.e+6, -1.e-6},204 205 { 1.e-6, 1.e+6},206 {-1.e-6, 1.e+6},207 {-1.e-6, -1.e+6},208 { 1.e-6, -1.e+6},209 210 { 1.e+6, 1.e+6},211 {-1.e+6, 1.e+6},212 {-1.e+6, -1.e+6},213 { 1.e+6, -1.e+6},214 215 {NAN, NAN},216 {-INFINITY, NAN},217 {-2, NAN},218 {-1, NAN},219 {-0.5, NAN},220 {-0., NAN},221 {+0., NAN},222 {0.5, NAN},223 {1, NAN},224 {2, NAN},225 {INFINITY, NAN},226 227 {NAN, -INFINITY},228 {-INFINITY, -INFINITY},229 {-2, -INFINITY},230 {-1, -INFINITY},231 {-0.5, -INFINITY},232 {-0., -INFINITY},233 {+0., -INFINITY},234 {0.5, -INFINITY},235 {1, -INFINITY},236 {2, -INFINITY},237 {INFINITY, -INFINITY},238 239 {NAN, -2},240 {-INFINITY, -2},241 {-2, -2},242 {-1, -2},243 {-0.5, -2},244 {-0., -2},245 {+0., -2},246 {0.5, -2},247 {1, -2},248 {2, -2},249 {INFINITY, -2},250 251 {NAN, -1},252 {-INFINITY, -1},253 {-2, -1},254 {-1, -1},255 {-0.5, -1},256 {-0., -1},257 {+0., -1},258 {0.5, -1},259 {1, -1},260 {2, -1},261 {INFINITY, -1},262 263 {NAN, -0.5},264 {-INFINITY, -0.5},265 {-2, -0.5},266 {-1, -0.5},267 {-0.5, -0.5},268 {-0., -0.5},269 {+0., -0.5},270 {0.5, -0.5},271 {1, -0.5},272 {2, -0.5},273 {INFINITY, -0.5},274 275 {NAN, -0.},276 {-INFINITY, -0.},277 {-2, -0.},278 {-1, -0.},279 {-0.5, -0.},280 {-0., -0.},281 {+0., -0.},282 {0.5, -0.},283 {1, -0.},284 {2, -0.},285 {INFINITY, -0.},286 287 {NAN, 0.},288 {-INFINITY, 0.},289 {-2, 0.},290 {-1, 0.},291 {-0.5, 0.},292 {-0., 0.},293 {+0., 0.},294 {0.5, 0.},295 {1, 0.},296 {2, 0.},297 {INFINITY, 0.},298 299 {NAN, 0.5},300 {-INFINITY, 0.5},301 {-2, 0.5},302 {-1, 0.5},303 {-0.5, 0.5},304 {-0., 0.5},305 {+0., 0.5},306 {0.5, 0.5},307 {1, 0.5},308 {2, 0.5},309 {INFINITY, 0.5},310 311 {NAN, 1},312 {-INFINITY, 1},313 {-2, 1},314 {-1, 1},315 {-0.5, 1},316 {-0., 1},317 {+0., 1},318 {0.5, 1},319 {1, 1},320 {2, 1},321 {INFINITY, 1},322 323 {NAN, 2},324 {-INFINITY, 2},325 {-2, 2},326 {-1, 2},327 {-0.5, 2},328 {-0., 2},329 {+0., 2},330 {0.5, 2},331 {1, 2},332 {2, 2},333 {INFINITY, 2},334 335 {NAN, INFINITY},336 {-INFINITY, INFINITY},337 {-2, INFINITY},338 {-1, INFINITY},339 {-0.5, INFINITY},340 {-0., INFINITY},341 {+0., INFINITY},342 {0.5, INFINITY},343 {1, INFINITY},344 {2, INFINITY},345 {INFINITY, INFINITY}346 347};348 349int main()350{351 const unsigned N = sizeof(x) / sizeof(x[0]);352 unsigned i, j;353 for (i = 0; i < N; ++i)354 {355 for (j = 0; j < N; ++j)356 {357 if (test__mulsc3(x[i][0], x[i][1], x[j][0], x[j][1]))358 return 1;359 }360 }361 362 return 0;363}364