1 | // RUN: %clang_builtins %s %librt -lm -o %t && %run %t |
---|---|

2 | // REQUIRES: librt_has_mulsc3 |

3 | // REQUIRES: c99-complex |

4 | |

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 + id |

12 | |

13 | COMPILER_RT_ABI float _Complex |

14 | __mulsc3(float __a, float __b, float __c, float __d); |

15 | |

16 | enum {zero, non_zero, inf, NaN, non_zero_nan}; |

17 | |

18 | int |

19 | classify(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 | |

42 | int 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 | |

193 | float 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 | |

349 | int 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 |