1/* $NetBSD: t_hypot.c,v 1.8 2024/05/13 20:28:15 rillig Exp $ */
2
3/*-
4 * Copyright (c) 2016 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <atf-c.h>
30#include <float.h>
31#include <math.h>
32
33#define	CHECK_EQ(i, hypot, a, b, c)					      \
34	ATF_CHECK_MSG(hypot(a, b) == (c),				      \
35	    "[%u] %s(%a, %a)=%a, expected %a",				      \
36	    (i), #hypot, (a), (b), hypot(a, b), (c))
37
38#define	CHECKL_EQ(i, hypot, a, b, c)					      \
39	ATF_CHECK_MSG(hypot(a, b) == (c),				      \
40	    "[%u] %s(%La, %La)=%La, expected %La",			      \
41	    (i), #hypot, (long double)(a), (long double)(b), hypot(a, b),     \
42	    (long double)(c))
43
44#define	CHECK_NAN(i, hypot, a, b)					      \
45	ATF_CHECK_MSG(isnan(hypot(a, b)),				      \
46	    "[%u] %s(%a, %a)=%a, expected NaN",				      \
47	    (i), #hypot, (a), (b), hypot(a, b))
48
49#define	CHECKL_NAN(i, hypot, a, b)					      \
50	ATF_CHECK_MSG(isnan(hypot(a, b)),				      \
51	    "[%u] %s(%La, %La)=%La, expected NaN",			      \
52	    (i), #hypot, (long double)(a), (long double)(b), hypot(a, b))
53
54static const float trivial_casesf[] = {
55	0,
56#ifdef __FLT_HAS_DENORM__
57	__FLT_DENORM_MIN__,
58	2*__FLT_DENORM_MIN__,
59	3*__FLT_DENORM_MIN__,
60	FLT_MIN - 3*__FLT_DENORM_MIN__,
61	FLT_MIN - 2*__FLT_DENORM_MIN__,
62	FLT_MIN - __FLT_DENORM_MIN__,
63#endif
64	FLT_MIN,
65	FLT_MIN*(1 + FLT_EPSILON),
66	FLT_MIN*(1 + 2*FLT_EPSILON),
67	2*FLT_MIN,
68	FLT_EPSILON/2,
69	FLT_EPSILON,
70	2*FLT_EPSILON,
71	1 - 3*FLT_EPSILON/2,
72	1 - 2*FLT_EPSILON/2,
73	1 - FLT_EPSILON/2,
74	1,
75	1 + FLT_EPSILON,
76	1 + 2*FLT_EPSILON,
77	1 + 3*FLT_EPSILON,
78	1.5 - 3*FLT_EPSILON,
79	1.5 - 2*FLT_EPSILON,
80	1.5 - FLT_EPSILON,
81	1.5,
82	1.5 + FLT_EPSILON,
83	1.5 + 2*FLT_EPSILON,
84	1.5 + 3*FLT_EPSILON,
85	2,
86	0.5/FLT_EPSILON - 0.5,
87	0.5/FLT_EPSILON,
88	0.5/FLT_EPSILON + 0.5,
89	1/FLT_EPSILON,
90	FLT_MAX,
91	INFINITY,
92};
93
94static const double trivial_cases[] = {
95	0,
96#ifdef __DBL_HAS_DENORM__
97	__DBL_DENORM_MIN__,
98	2*__DBL_DENORM_MIN__,
99	3*__DBL_DENORM_MIN__,
100	DBL_MIN - 3*__DBL_DENORM_MIN__,
101	DBL_MIN - 2*__DBL_DENORM_MIN__,
102	DBL_MIN - __DBL_DENORM_MIN__,
103#endif
104	DBL_MIN,
105	DBL_MIN*(1 + DBL_EPSILON),
106	DBL_MIN*(1 + 2*DBL_EPSILON),
107	2*DBL_MIN,
108	DBL_EPSILON/2,
109	DBL_EPSILON,
110	2*DBL_EPSILON,
111	1 - 3*DBL_EPSILON/2,
112	1 - 2*DBL_EPSILON/2,
113	1 - DBL_EPSILON/2,
114	1,
115	1 + DBL_EPSILON,
116	1 + 2*DBL_EPSILON,
117	1 + 3*DBL_EPSILON,
118	1.5 - 3*DBL_EPSILON,
119	1.5 - 2*DBL_EPSILON,
120	1.5 - DBL_EPSILON,
121	1.5,
122	1.5 + DBL_EPSILON,
123	1.5 + 2*DBL_EPSILON,
124	1.5 + 3*DBL_EPSILON,
125	2,
126	1/FLT_EPSILON - 0.5,
127	1/FLT_EPSILON,
128	1/FLT_EPSILON + 0.5,
129	0.5/DBL_EPSILON - 0.5,
130	0.5/DBL_EPSILON,
131	0.5/DBL_EPSILON + 0.5,
132	1/DBL_EPSILON,
133	DBL_MAX,
134	INFINITY,
135};
136
137static const long double trivial_casesl[] = {
138	0,
139#ifdef __LDBL_HAS_DENORM__
140	__LDBL_DENORM_MIN__,
141	2*__LDBL_DENORM_MIN__,
142	3*__LDBL_DENORM_MIN__,
143	LDBL_MIN - 3*__LDBL_DENORM_MIN__,
144	LDBL_MIN - 2*__LDBL_DENORM_MIN__,
145	LDBL_MIN - __LDBL_DENORM_MIN__,
146#endif
147	LDBL_MIN,
148	LDBL_MIN*(1 + LDBL_EPSILON),
149	LDBL_MIN*(1 + 2*LDBL_EPSILON),
150	2*LDBL_MIN,
151	LDBL_EPSILON/2,
152	LDBL_EPSILON,
153	2*LDBL_EPSILON,
154	1 - 3*LDBL_EPSILON/2,
155	1 - 2*LDBL_EPSILON/2,
156	1 - LDBL_EPSILON/2,
157	1,
158	1 + LDBL_EPSILON,
159	1 + 2*LDBL_EPSILON,
160	1 + 3*LDBL_EPSILON,
161	1.5 - 3*LDBL_EPSILON,
162	1.5 - 2*LDBL_EPSILON,
163	1.5 - LDBL_EPSILON,
164	1.5,
165	1.5 + LDBL_EPSILON,
166	1.5 + 2*LDBL_EPSILON,
167	1.5 + 3*LDBL_EPSILON,
168	2,
169	1/FLT_EPSILON - 0.5,
170	1/FLT_EPSILON,
171	1/FLT_EPSILON + 0.5,
172#ifdef __HAVE_LONG_DOUBLE
173	1/DBL_EPSILON - 0.5L,
174	1/DBL_EPSILON,
175	1/DBL_EPSILON + 0.5L,
176#endif
177	0.5/LDBL_EPSILON - 0.5,
178	0.5/LDBL_EPSILON,
179	0.5/LDBL_EPSILON + 0.5,
180	1/LDBL_EPSILON,
181	LDBL_MAX,
182	INFINITY,
183};
184
185ATF_TC(hypotf_trivial);
186ATF_TC_HEAD(hypotf_trivial, tc)
187{
188	atf_tc_set_md_var(tc, "descr", "hypotf(x,0) and hypotf(0,x)");
189}
190ATF_TC_BODY(hypotf_trivial, tc)
191{
192	unsigned i;
193
194	for (i = 0; i < __arraycount(trivial_casesf); i++) {
195		volatile float x = trivial_casesf[i];
196
197		CHECK_EQ(i, hypotf, x, +0., x);
198		CHECK_EQ(i, hypotf, x, -0., x);
199		CHECK_EQ(i, hypotf, +0., x, x);
200		CHECK_EQ(i, hypotf, -0., x, x);
201		CHECK_EQ(i, hypotf, -x, +0., x);
202		CHECK_EQ(i, hypotf, -x, -0., x);
203		CHECK_EQ(i, hypotf, +0., -x, x);
204		CHECK_EQ(i, hypotf, -0., -x, x);
205
206		if (isinf(INFINITY)) {
207			CHECK_EQ(i, hypotf, x, +INFINITY, INFINITY);
208			CHECK_EQ(i, hypotf, x, -INFINITY, INFINITY);
209			CHECK_EQ(i, hypotf, +INFINITY, x, INFINITY);
210			CHECK_EQ(i, hypotf, -INFINITY, x, INFINITY);
211			CHECK_EQ(i, hypotf, -x, +INFINITY, INFINITY);
212			CHECK_EQ(i, hypotf, -x, -INFINITY, INFINITY);
213			CHECK_EQ(i, hypotf, +INFINITY, -x, INFINITY);
214			CHECK_EQ(i, hypotf, -INFINITY, -x, INFINITY);
215		}
216
217#ifdef NAN
218		if (isinf(x)) {
219			CHECK_EQ(i, hypotf, x, NAN, INFINITY);
220			CHECK_EQ(i, hypotf, NAN, x, INFINITY);
221			CHECK_EQ(i, hypotf, -x, NAN, INFINITY);
222			CHECK_EQ(i, hypotf, NAN, -x, INFINITY);
223		} else {
224			CHECK_NAN(i, hypotf, x, NAN);
225			CHECK_NAN(i, hypotf, NAN, x);
226			CHECK_NAN(i, hypotf, -x, NAN);
227			CHECK_NAN(i, hypotf, NAN, -x);
228		}
229#endif
230	}
231}
232
233ATF_TC(hypot_trivial);
234ATF_TC_HEAD(hypot_trivial, tc)
235{
236	atf_tc_set_md_var(tc, "descr", "hypot(x,0) and hypot(0,x)");
237}
238ATF_TC_BODY(hypot_trivial, tc)
239{
240	unsigned i;
241
242	for (i = 0; i < __arraycount(trivial_casesf); i++) {
243		volatile double x = trivial_casesf[i];
244
245		CHECK_EQ(i, hypot, x, +0., x);
246		CHECK_EQ(i, hypot, x, -0., x);
247		CHECK_EQ(i, hypot, +0., x, x);
248		CHECK_EQ(i, hypot, -0., x, x);
249		CHECK_EQ(i, hypot, -x, +0., x);
250		CHECK_EQ(i, hypot, -x, -0., x);
251		CHECK_EQ(i, hypot, +0., -x, x);
252		CHECK_EQ(i, hypot, -0., -x, x);
253
254		if (isinf(INFINITY)) {
255			CHECK_EQ(i, hypot, x, +INFINITY, INFINITY);
256			CHECK_EQ(i, hypot, x, -INFINITY, INFINITY);
257			CHECK_EQ(i, hypot, +INFINITY, x, INFINITY);
258			CHECK_EQ(i, hypot, -INFINITY, x, INFINITY);
259			CHECK_EQ(i, hypot, -x, +INFINITY, INFINITY);
260			CHECK_EQ(i, hypot, -x, -INFINITY, INFINITY);
261			CHECK_EQ(i, hypot, +INFINITY, -x, INFINITY);
262			CHECK_EQ(i, hypot, -INFINITY, -x, INFINITY);
263		}
264
265#ifdef NAN
266		if (isinf(x)) {
267			CHECK_EQ(i, hypot, x, NAN, INFINITY);
268			CHECK_EQ(i, hypot, NAN, x, INFINITY);
269			CHECK_EQ(i, hypot, -x, NAN, INFINITY);
270			CHECK_EQ(i, hypot, NAN, -x, INFINITY);
271		} else {
272			CHECK_NAN(i, hypot, x, NAN);
273			CHECK_NAN(i, hypot, NAN, x);
274			CHECK_NAN(i, hypot, -x, NAN);
275			CHECK_NAN(i, hypot, NAN, -x);
276		}
277#endif
278	}
279
280	for (i = 0; i < __arraycount(trivial_cases); i++) {
281		volatile double x = trivial_cases[i];
282
283		CHECK_EQ(i, hypot, x, +0., x);
284		CHECK_EQ(i, hypot, x, -0., x);
285		CHECK_EQ(i, hypot, +0., x, x);
286		CHECK_EQ(i, hypot, -0., x, x);
287		CHECK_EQ(i, hypot, -x, +0., x);
288		CHECK_EQ(i, hypot, -x, -0., x);
289		CHECK_EQ(i, hypot, +0., -x, x);
290		CHECK_EQ(i, hypot, -0., -x, x);
291
292		if (isinf(INFINITY)) {
293			CHECK_EQ(i, hypot, x, +INFINITY, INFINITY);
294			CHECK_EQ(i, hypot, x, -INFINITY, INFINITY);
295			CHECK_EQ(i, hypot, +INFINITY, x, INFINITY);
296			CHECK_EQ(i, hypot, -INFINITY, x, INFINITY);
297			CHECK_EQ(i, hypot, -x, +INFINITY, INFINITY);
298			CHECK_EQ(i, hypot, -x, -INFINITY, INFINITY);
299			CHECK_EQ(i, hypot, +INFINITY, -x, INFINITY);
300			CHECK_EQ(i, hypot, -INFINITY, -x, INFINITY);
301		}
302
303#ifdef NAN
304		if (isinf(x)) {
305			CHECK_EQ(i, hypot, x, NAN, INFINITY);
306			CHECK_EQ(i, hypot, NAN, x, INFINITY);
307			CHECK_EQ(i, hypot, -x, NAN, INFINITY);
308			CHECK_EQ(i, hypot, NAN, -x, INFINITY);
309		} else {
310			CHECK_NAN(i, hypot, x, NAN);
311			CHECK_NAN(i, hypot, NAN, x);
312			CHECK_NAN(i, hypot, -x, NAN);
313			CHECK_NAN(i, hypot, NAN, -x);
314		}
315#endif
316	}
317}
318
319ATF_TC(hypotl_trivial);
320ATF_TC_HEAD(hypotl_trivial, tc)
321{
322	atf_tc_set_md_var(tc, "descr", "hypotl(x,0) and hypotl(0,x)");
323}
324ATF_TC_BODY(hypotl_trivial, tc)
325{
326	unsigned i;
327
328	for (i = 0; i < __arraycount(trivial_casesf); i++) {
329		volatile long double x = trivial_casesf[i];
330
331		CHECKL_EQ(i, hypotl, x, +0.L, x);
332		CHECKL_EQ(i, hypotl, x, -0.L, x);
333		CHECKL_EQ(i, hypotl, +0.L, x, x);
334		CHECKL_EQ(i, hypotl, -0.L, x, x);
335		CHECKL_EQ(i, hypotl, -x, +0.L, x);
336		CHECKL_EQ(i, hypotl, -x, -0.L, x);
337		CHECKL_EQ(i, hypotl, +0.L, -x, x);
338		CHECKL_EQ(i, hypotl, -0.L, -x, x);
339
340		if (isinf(INFINITY)) {
341			CHECKL_EQ(i, hypotl, x, +INFINITY, INFINITY);
342			CHECKL_EQ(i, hypotl, x, -INFINITY, INFINITY);
343			CHECKL_EQ(i, hypotl, +INFINITY, x, INFINITY);
344			CHECKL_EQ(i, hypotl, -INFINITY, x, INFINITY);
345			CHECKL_EQ(i, hypotl, -x, +INFINITY, INFINITY);
346			CHECKL_EQ(i, hypotl, -x, -INFINITY, INFINITY);
347			CHECKL_EQ(i, hypotl, +INFINITY, -x, INFINITY);
348			CHECKL_EQ(i, hypotl, -INFINITY, -x, INFINITY);
349		}
350
351#ifdef NAN
352		if (isinf(x)) {
353			CHECKL_EQ(i, hypotl, x, NAN, INFINITY);
354			CHECKL_EQ(i, hypotl, NAN, x, INFINITY);
355			CHECKL_EQ(i, hypotl, -x, NAN, INFINITY);
356			CHECKL_EQ(i, hypotl, NAN, -x, INFINITY);
357		} else {
358			CHECKL_NAN(i, hypotl, x, NAN);
359			CHECKL_NAN(i, hypotl, NAN, x);
360			CHECKL_NAN(i, hypotl, -x, NAN);
361			CHECKL_NAN(i, hypotl, NAN, -x);
362		}
363#endif
364	}
365
366	for (i = 0; i < __arraycount(trivial_cases); i++) {
367		volatile long double x = trivial_cases[i];
368
369		CHECKL_EQ(i, hypotl, x, +0.L, x);
370		CHECKL_EQ(i, hypotl, x, -0.L, x);
371		CHECKL_EQ(i, hypotl, +0.L, x, x);
372		CHECKL_EQ(i, hypotl, -0.L, x, x);
373		CHECKL_EQ(i, hypotl, -x, +0.L, x);
374		CHECKL_EQ(i, hypotl, -x, -0.L, x);
375		CHECKL_EQ(i, hypotl, +0.L, -x, x);
376		CHECKL_EQ(i, hypotl, -0.L, -x, x);
377
378		if (isinf(INFINITY)) {
379			CHECKL_EQ(i, hypotl, x, +INFINITY, INFINITY);
380			CHECKL_EQ(i, hypotl, x, -INFINITY, INFINITY);
381			CHECKL_EQ(i, hypotl, +INFINITY, x, INFINITY);
382			CHECKL_EQ(i, hypotl, -INFINITY, x, INFINITY);
383			CHECKL_EQ(i, hypotl, -x, +INFINITY, INFINITY);
384			CHECKL_EQ(i, hypotl, -x, -INFINITY, INFINITY);
385			CHECKL_EQ(i, hypotl, +INFINITY, -x, INFINITY);
386			CHECKL_EQ(i, hypotl, -INFINITY, -x, INFINITY);
387		}
388
389#ifdef NAN
390		if (isinf(x)) {
391			CHECKL_EQ(i, hypotl, x, NAN, INFINITY);
392			CHECKL_EQ(i, hypotl, NAN, x, INFINITY);
393			CHECKL_EQ(i, hypotl, -x, NAN, INFINITY);
394			CHECKL_EQ(i, hypotl, NAN, -x, INFINITY);
395		} else {
396			CHECKL_NAN(i, hypotl, x, NAN);
397			CHECKL_NAN(i, hypotl, NAN, x);
398			CHECKL_NAN(i, hypotl, -x, NAN);
399			CHECKL_NAN(i, hypotl, NAN, -x);
400		}
401#endif
402	}
403
404	for (i = 0; i < __arraycount(trivial_casesl); i++) {
405		volatile long double x = trivial_casesl[i];
406
407		CHECKL_EQ(i, hypotl, x, +0.L, x);
408		CHECKL_EQ(i, hypotl, x, -0.L, x);
409		CHECKL_EQ(i, hypotl, +0.L, x, x);
410		CHECKL_EQ(i, hypotl, -0.L, x, x);
411		CHECKL_EQ(i, hypotl, -x, +0.L, x);
412		CHECKL_EQ(i, hypotl, -x, -0.L, x);
413		CHECKL_EQ(i, hypotl, +0.L, -x, x);
414		CHECKL_EQ(i, hypotl, -0.L, -x, x);
415
416		if (isinf(INFINITY)) {
417			CHECKL_EQ(i, hypotl, x, +INFINITY, INFINITY);
418			CHECKL_EQ(i, hypotl, x, -INFINITY, INFINITY);
419			CHECKL_EQ(i, hypotl, +INFINITY, x, INFINITY);
420			CHECKL_EQ(i, hypotl, -INFINITY, x, INFINITY);
421			CHECKL_EQ(i, hypotl, -x, +INFINITY, INFINITY);
422			CHECKL_EQ(i, hypotl, -x, -INFINITY, INFINITY);
423			CHECKL_EQ(i, hypotl, +INFINITY, -x, INFINITY);
424			CHECKL_EQ(i, hypotl, -INFINITY, -x, INFINITY);
425		}
426
427#ifdef NAN
428		if (isinf(x)) {
429			CHECKL_EQ(i, hypotl, x, NAN, INFINITY);
430			CHECKL_EQ(i, hypotl, NAN, x, INFINITY);
431			CHECKL_EQ(i, hypotl, -x, NAN, INFINITY);
432			CHECKL_EQ(i, hypotl, NAN, -x, INFINITY);
433		} else {
434			CHECKL_NAN(i, hypotl, x, NAN);
435			CHECKL_NAN(i, hypotl, NAN, x);
436			CHECKL_NAN(i, hypotl, -x, NAN);
437			CHECKL_NAN(i, hypotl, NAN, -x);
438		}
439#endif
440	}
441}
442
443/*
444 * All primitive Pythagorean triples are generated from coprime
445 * integers m > n > 0 by Euclid's formula,
446 *
447 *	a = m^2 - n^2
448 *	b = 2 m n,
449 *	c = m^2 + n^2.
450 *
451 * We test cases with various different numbers and positions of bits,
452 * generated by this formula.
453 *
454 * If you're curious, you can recover m and n from a, b, and c by
455 *
456 *	m = sqrt((a + c)/2)
457 *	n = b/2m.
458 */
459
460__CTASSERT(FLT_MANT_DIG >= 24);
461static const struct {
462	float a, b, c;
463} exact_casesf[] = {
464	{ 3, 4, 5 },
465	{ 5, 12, 13 },
466	{ 9, 12, 15 },
467	{ 0x1001, 0x801000, 0x801001 },
468	{ 4248257, 1130976, 4396225 },
469};
470
471__CTASSERT(DBL_MANT_DIG >= 53);
472static const struct {
473	double a, b, c;
474} exact_cases[] = {
475	{ 3378249543467007, 4505248894795776, 5631148868747265 },
476	{ 0x7ffffff, 0x1ffffff8000000, 0x1ffffff8000001 },
477#if DBL_MANT_DIG >= 56
478	{ 13514123525517439, 18018830919909120, 22523538851237761 },
479	{ 0x1fffffff, 0x1ffffffe0000000, 0x1ffffffe0000001 },
480#endif
481};
482
483#if LDBL_MANT_DIG >= 64
484static const struct {
485	long double a, b, c;
486} exact_casesl[] = {
487	{ 3458976450080784639, 4611968592949214720, 5764960744407842561 },
488	{ 0x200000000, 0x7ffffffffffffffe, 0x8000000000000002 },
489#if LDBL_MANT_DIG >= 113
490	{ 973555668229277869436257492279295.L,
491	  1298074224305703705819019479072768.L,
492	  1622592780382129686316970078625793.L },
493	{ 0x1ffffffffffffff,
494	  0x1fffffffffffffe00000000000000p0L,
495	  0x1fffffffffffffe00000000000001p0L },
496#endif
497};
498#endif
499
500ATF_TC(hypotf_exact);
501ATF_TC_HEAD(hypotf_exact, tc)
502{
503	atf_tc_set_md_var(tc, "descr", "hypotf on scaled Pythagorean triples");
504}
505ATF_TC_BODY(hypotf_exact, tc)
506{
507	unsigned i;
508
509	for (i = 0; i < __arraycount(exact_casesf); i++) {
510		int s;
511
512		for (s = FLT_MIN_EXP;
513		     s < FLT_MAX_EXP - FLT_MANT_DIG;
514		     s += (FLT_MAX_EXP - FLT_MANT_DIG - FLT_MIN_EXP)/5) {
515			volatile double a = ldexpf(exact_casesf[i].a, s);
516			volatile double b = ldexpf(exact_casesf[i].b, s);
517			float c = ldexpf(exact_casesf[i].c, s);
518
519			CHECK_EQ(i, hypot, a, b, c);
520			CHECK_EQ(i, hypot, b, a, c);
521			CHECK_EQ(i, hypot, a, -b, c);
522			CHECK_EQ(i, hypot, b, -a, c);
523			CHECK_EQ(i, hypot, -a, b, c);
524			CHECK_EQ(i, hypot, -b, a, c);
525			CHECK_EQ(i, hypot, -a, -b, c);
526			CHECK_EQ(i, hypot, -b, -a, c);
527		}
528	}
529}
530
531ATF_TC(hypot_exact);
532ATF_TC_HEAD(hypot_exact, tc)
533{
534	atf_tc_set_md_var(tc, "descr", "hypot on scaled Pythagorean triples");
535}
536ATF_TC_BODY(hypot_exact, tc)
537{
538	unsigned i;
539
540	for (i = 0; i < __arraycount(exact_casesf); i++) {
541		int s;
542
543		for (s = DBL_MIN_EXP;
544		     s < DBL_MAX_EXP - DBL_MANT_DIG;
545		     s += (DBL_MAX_EXP - DBL_MANT_DIG - DBL_MIN_EXP)/5) {
546			volatile double a = ldexp(exact_casesf[i].a, s);
547			volatile double b = ldexp(exact_casesf[i].b, s);
548			double c = ldexp(exact_casesf[i].c, s);
549
550			CHECK_EQ(i, hypot, a, b, c);
551			CHECK_EQ(i, hypot, b, a, c);
552			CHECK_EQ(i, hypot, a, -b, c);
553			CHECK_EQ(i, hypot, b, -a, c);
554			CHECK_EQ(i, hypot, -a, b, c);
555			CHECK_EQ(i, hypot, -b, a, c);
556			CHECK_EQ(i, hypot, -a, -b, c);
557			CHECK_EQ(i, hypot, -b, -a, c);
558		}
559	}
560
561	for (i = 0; i < __arraycount(exact_cases); i++) {
562		int s;
563
564		for (s = DBL_MIN_EXP;
565		     s < DBL_MAX_EXP - DBL_MANT_DIG;
566		     s += (DBL_MAX_EXP - DBL_MANT_DIG - DBL_MIN_EXP)/5) {
567			volatile double a = ldexp(exact_cases[i].a, s);
568			volatile double b = ldexp(exact_cases[i].b, s);
569			double c = ldexp(exact_cases[i].c, s);
570
571			CHECK_EQ(i, hypot, a, b, c);
572			CHECK_EQ(i, hypot, b, a, c);
573			CHECK_EQ(i, hypot, a, -b, c);
574			CHECK_EQ(i, hypot, b, -a, c);
575			CHECK_EQ(i, hypot, -a, b, c);
576			CHECK_EQ(i, hypot, -b, a, c);
577			CHECK_EQ(i, hypot, -a, -b, c);
578			CHECK_EQ(i, hypot, -b, -a, c);
579		}
580	}
581}
582
583ATF_TC(hypotl_exact);
584ATF_TC_HEAD(hypotl_exact, tc)
585{
586	atf_tc_set_md_var(tc, "descr", "hypotl on scaled Pythagorean triples");
587}
588ATF_TC_BODY(hypotl_exact, tc)
589{
590	unsigned i;
591
592	for (i = 0; i < __arraycount(exact_casesf); i++) {
593		int s;
594
595		for (s = LDBL_MIN_EXP;
596		     s < LDBL_MAX_EXP - LDBL_MANT_DIG;
597		     s += (LDBL_MAX_EXP - LDBL_MANT_DIG - LDBL_MIN_EXP)/5) {
598			volatile long double a = ldexpl(exact_casesf[i].a, s);
599			volatile long double b = ldexpl(exact_casesf[i].b, s);
600			long double c = ldexpl(exact_casesf[i].c, s);
601
602			CHECKL_EQ(i, hypotl, a, b, c);
603			CHECKL_EQ(i, hypotl, b, a, c);
604			CHECKL_EQ(i, hypotl, a, -b, c);
605			CHECKL_EQ(i, hypotl, b, -a, c);
606			CHECKL_EQ(i, hypotl, -a, b, c);
607			CHECKL_EQ(i, hypotl, -b, a, c);
608			CHECKL_EQ(i, hypotl, -a, -b, c);
609			CHECKL_EQ(i, hypotl, -b, -a, c);
610		}
611	}
612
613	for (i = 0; i < __arraycount(exact_cases); i++) {
614		int s;
615
616		for (s = LDBL_MIN_EXP;
617		     s < LDBL_MAX_EXP - LDBL_MANT_DIG;
618		     s += (LDBL_MAX_EXP - LDBL_MANT_DIG - LDBL_MIN_EXP)/5) {
619			volatile long double a = ldexpl(exact_cases[i].a, s);
620			volatile long double b = ldexpl(exact_cases[i].b, s);
621			long double c = ldexpl(exact_cases[i].c, s);
622
623			CHECKL_EQ(i, hypotl, a, b, c);
624			CHECKL_EQ(i, hypotl, b, a, c);
625			CHECKL_EQ(i, hypotl, a, -b, c);
626			CHECKL_EQ(i, hypotl, b, -a, c);
627			CHECKL_EQ(i, hypotl, -a, b, c);
628			CHECKL_EQ(i, hypotl, -b, a, c);
629			CHECKL_EQ(i, hypotl, -a, -b, c);
630			CHECKL_EQ(i, hypotl, -b, -a, c);
631		}
632	}
633
634#if LDBL_MANT_DIG >= 64
635	for (i = 0; i < __arraycount(exact_casesl); i++) {
636		int s;
637
638		for (s = LDBL_MIN_EXP;
639		     s < LDBL_MAX_EXP - LDBL_MANT_DIG;
640		     s += (LDBL_MAX_EXP - LDBL_MANT_DIG - LDBL_MIN_EXP)/5) {
641			volatile long double a = ldexpl(exact_casesl[i].a, s);
642			volatile long double b = ldexpl(exact_casesl[i].b, s);
643			long double c = ldexpl(exact_casesl[i].c, s);
644
645			CHECKL_EQ(i, hypotl, a, b, c);
646			CHECKL_EQ(i, hypotl, b, a, c);
647			CHECKL_EQ(i, hypotl, a, -b, c);
648			CHECKL_EQ(i, hypotl, b, -a, c);
649			CHECKL_EQ(i, hypotl, -a, b, c);
650			CHECKL_EQ(i, hypotl, -b, a, c);
651			CHECKL_EQ(i, hypotl, -a, -b, c);
652			CHECKL_EQ(i, hypotl, -b, -a, c);
653		}
654	}
655#endif
656}
657
658ATF_TC(hypot_nan);
659ATF_TC_HEAD(hypot_nan, tc)
660{
661	atf_tc_set_md_var(tc, "descr", "hypot/hypotf/hypotl(NAN, NAN)");
662}
663ATF_TC_BODY(hypot_nan, tc)
664{
665#ifdef NAN
666	CHECK_NAN(0, hypot, NAN, NAN);
667	CHECK_NAN(1, hypotf, NAN, NAN);
668	CHECKL_NAN(2, hypotl, NAN, NAN);
669#else
670	atf_tc_skip("no NaNs on this architecture");
671#endif
672}
673
674ATF_TC(pr50698);
675ATF_TC_HEAD(pr50698, tc)
676{
677	atf_tc_set_md_var(tc, "descr", "Check for the bug of PR lib/50698");
678}
679
680ATF_TC_BODY(pr50698, tc)
681{
682	volatile float a = 1e-18f;
683	float val = hypotf(a, a);
684	ATF_CHECK(!isinf(val));
685	ATF_CHECK(!isnan(val));
686}
687
688ATF_TP_ADD_TCS(tp)
689{
690
691	ATF_TP_ADD_TC(tp, hypot_exact);
692	ATF_TP_ADD_TC(tp, hypot_nan);
693	ATF_TP_ADD_TC(tp, hypot_trivial);
694	ATF_TP_ADD_TC(tp, hypotf_exact);
695	ATF_TP_ADD_TC(tp, hypotf_trivial);
696	ATF_TP_ADD_TC(tp, hypotl_exact);
697	ATF_TP_ADD_TC(tp, hypotl_trivial);
698	ATF_TP_ADD_TC(tp, pr50698);
699
700	return atf_no_error();
701}
702