Import of code from c-tap-harness
[openafs.git] / src / external / c-tap-harness / tests / tap / float.c
1 /*
2  * Utility routines for writing floating point tests.
3  *
4  * Currently provides only one function, which checks whether a double is
5  * equal to an expected value within a given epsilon.  This is broken into a
6  * separate source file from the rest of the basic C TAP library because it
7  * may require linking with -lm on some platforms, and the package may not
8  * otherwise care about floating point.
9  *
10  * This file is part of C TAP Harness.  The current version plus supporting
11  * documentation is at <https://www.eyrie.org/~eagle/software/c-tap-harness/>.
12  *
13  * Copyright 2008, 2010, 2012-2019 Russ Allbery <eagle@eyrie.org>
14  *
15  * Permission is hereby granted, free of charge, to any person obtaining a
16  * copy of this software and associated documentation files (the "Software"),
17  * to deal in the Software without restriction, including without limitation
18  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
19  * and/or sell copies of the Software, and to permit persons to whom the
20  * Software is furnished to do so, subject to the following conditions:
21  *
22  * The above copyright notice and this permission notice shall be included in
23  * all copies or substantial portions of the Software.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
28  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
31  * DEALINGS IN THE SOFTWARE.
32  *
33  * SPDX-License-Identifier: MIT
34  */
35
36 /* Required for isnan() and isinf(). */
37 #if defined(__STRICT_ANSI__) || defined(PEDANTIC)
38 #    ifndef _XOPEN_SOURCE
39 #        define _XOPEN_SOURCE 600
40 #    endif
41 #endif
42
43 #include <math.h>
44 #include <stdarg.h>
45 #include <stdio.h>
46
47 #include <tests/tap/basic.h>
48 #include <tests/tap/float.h>
49
50 /*
51  * Clang 4.0.1 gets very confused by this file and produces warnings about
52  * floating point implicit conversion from the isnan() and isinf() macros.
53  */
54 #if defined(__llvm__) || defined(__clang__)
55 #    pragma clang diagnostic ignored "-Wconversion"
56 #    pragma clang diagnostic ignored "-Wdouble-promotion"
57 #endif
58
59 /*
60  * Returns true if the two doubles are equal infinities, false otherwise.
61  * This requires a bit of machination since isinf is not required to return
62  * different values for positive and negative infinity, and we're trying to
63  * avoid direct comparisons between floating point numbers.
64  */
65 static int
66 is_equal_infinity(double left, double right)
67 {
68     if (!isinf(left) || !isinf(right))
69         return 0;
70     return !!(left < 0) == !!(right < 0);
71 }
72
73 /*
74  * Takes two doubles and requires they be within epsilon of each other.
75  */
76 int
77 is_double(double left, double right, double epsilon, const char *format, ...)
78 {
79     va_list args;
80     int success;
81
82     va_start(args, format);
83     fflush(stderr);
84     if ((isnan(left) && isnan(right)) || is_equal_infinity(left, right)
85         || fabs(left - right) <= epsilon) {
86         success = 1;
87         okv(1, format, args);
88     } else {
89         success = 0;
90         diag(" left: %g", left);
91         diag("right: %g", right);
92         okv(0, format, args);
93     }
94     va_end(args);
95     return success;
96 }