| 1 | /*- |
| 2 | * SPDX-License-Identifier: BSD-2-Clause |
| 3 | * |
| 4 | * Copyright (c) 2004 Stefan Farfeleder. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Copyright (c) 2012 Ed Schouten <ed@FreeBSD.org> |
| 8 | * All rights reserved. |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions |
| 12 | * are met: |
| 13 | * 1. Redistributions of source code must retain the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer. |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer in the |
| 17 | * documentation and/or other materials provided with the distribution. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 29 | * SUCH DAMAGE. |
| 30 | */ |
| 31 | |
| 32 | #ifndef _TGMATH_H_ |
| 33 | #define	_TGMATH_H_ |
| 34 | |
| 35 | #include <complex.h> |
| 36 | #include <math.h> |
| 37 | |
| 38 | /* |
| 39 | * This implementation of <tgmath.h> uses the two following macros, |
| 40 | * which are based on the macros described in C11 proposal N1404: |
| 41 | * __tg_impl_simple(x, y, z, fnl, fn, fnf, ...) |
| 42 | *	Invokes fnl() if the corresponding real type of x, y or z is long |
| 43 | *	double, fn() if it is double or any has an integer type, and fnf() |
| 44 | *	otherwise. |
| 45 | * __tg_impl_full(x, y, cfnl, cfn, cfnf, fnl, fn, fnf, ...) |
| 46 | *	Invokes [c]fnl() if the corresponding real type of x or y is long |
| 47 | *	double, [c]fn() if it is double or any has an integer type, and |
| 48 | *	[c]fnf() otherwise. The function with the 'c' prefix is called if |
| 49 | *	any of x or y is a complex number. |
| 50 | * Both macros call the chosen function with all additional arguments passed |
| 51 | * to them, as given by __VA_ARGS__. |
| 52 | * |
| 53 | * Note that these macros cannot be implemented with C's ?: operator, |
| 54 | * because the return type of the whole expression would incorrectly be long |
| 55 | * double complex regardless of the argument types. |
| 56 | * |
| 57 | * The structure of the C11 implementation of these macros can in |
| 58 | * principle be reused for non-C11 compilers, but due to an integer |
| 59 | * promotion bug for complex types in GCC 4.2, simply let non-C11 |
| 60 | * compilers use an inefficient yet reliable version. |
| 61 | */ |
| 62 | |
| 63 | #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) || \ |
| 64 | __has_extension(c_generic_selections) |
| 65 | #define	__tg_generic(x, cfnl, cfn, cfnf, fnl, fn, fnf)			\ |
| 66 | 	_Generic(x,							\ |
| 67 | 		long double _Complex: cfnl,				\ |
| 68 | 		double _Complex: cfn,					\ |
| 69 | 		float _Complex: cfnf,					\ |
| 70 | 		long double: fnl,					\ |
| 71 | 		default: fn,						\ |
| 72 | 		float: fnf						\ |
| 73 | 	) |
| 74 | #define	__tg_type(x)							\ |
| 75 | 	__tg_generic(x, (long double _Complex)0, (double _Complex)0,	\ |
| 76 | 	 (float _Complex)0, (long double)0, (double)0, (float)0) |
| 77 | #define	__tg_impl_simple(x, y, z, fnl, fn, fnf, ...)			\ |
| 78 | 	__tg_generic(							\ |
| 79 | 	 __tg_type(x) + __tg_type(y) + __tg_type(z),			\ |
| 80 | 	 fnl, fn, fnf, fnl, fn, fnf)(__VA_ARGS__) |
| 81 | #define	__tg_impl_full(x, y, cfnl, cfn, cfnf, fnl, fn, fnf, ...)	\ |
| 82 | 	__tg_generic(							\ |
| 83 | 	 __tg_type(x) + __tg_type(y),				\ |
| 84 | 	 cfnl, cfn, cfnf, fnl, fn, fnf)(__VA_ARGS__) |
| 85 | #elif defined(__generic) |
| 86 | #define	__tg_generic_simple(x, fnl, fn, fnf)				\ |
| 87 | 	__generic(x, long double _Complex, fnl,				\ |
| 88 | 	 __generic(x, double _Complex, fn,				\ |
| 89 | 	 __generic(x, float _Complex, fnf,			\ |
| 90 | 	 __generic(x, long double, fnl,			\ |
| 91 | 	 __generic(x, float, fnf, fn))))) |
| 92 | #define	__tg_impl_simple(x, y, z, fnl, fn, fnf, ...)			\ |
| 93 | 	__tg_generic_simple(x,						\ |
| 94 | 	 __tg_generic_simple(y,					\ |
| 95 | 	 __tg_generic_simple(z, fnl, fnl, fnl),			\ |
| 96 | 	 __tg_generic_simple(z, fnl, fnl, fnl),			\ |
| 97 | 	 __tg_generic_simple(z, fnl, fnl, fnl)),			\ |
| 98 | 	 __tg_generic_simple(y,					\ |
| 99 | 	 __tg_generic_simple(z, fnl, fnl, fnl),			\ |
| 100 | 	 __tg_generic_simple(z, fnl, fn , fn ),			\ |
| 101 | 	 __tg_generic_simple(z, fnl, fn , fn )),			\ |
| 102 | 	 __tg_generic_simple(y,					\ |
| 103 | 	 __tg_generic_simple(z, fnl, fnl, fnl),			\ |
| 104 | 	 __tg_generic_simple(z, fnl, fn , fn ),			\ |
| 105 | 	 __tg_generic_simple(z, fnl, fn , fnf)))(__VA_ARGS__) |
| 106 | #define	__tg_generic_full(x, cfnl, cfn, cfnf, fnl, fn, fnf)		\ |
| 107 | 	__generic(x, long double _Complex, cfnl,			\ |
| 108 | 	 __generic(x, double _Complex, cfn,				\ |
| 109 | 	 __generic(x, float _Complex, cfnf,			\ |
| 110 | 	 __generic(x, long double, fnl,			\ |
| 111 | 	 __generic(x, float, fnf, fn))))) |
| 112 | #define	__tg_impl_full(x, y, cfnl, cfn, cfnf, fnl, fn, fnf, ...)	\ |
| 113 | 	__tg_generic_full(x,						\ |
| 114 | 	 __tg_generic_full(y, cfnl, cfnl, cfnl, cfnl, cfnl, cfnl),	\ |
| 115 | 	 __tg_generic_full(y, cfnl, cfn , cfn , cfnl, cfn , cfn ),	\ |
| 116 | 	 __tg_generic_full(y, cfnl, cfn , cfnf, cfnl, cfn , cfnf),	\ |
| 117 | 	 __tg_generic_full(y, cfnl, cfnl, cfnl, fnl , fnl , fnl ),	\ |
| 118 | 	 __tg_generic_full(y, cfnl, cfn , cfn , fnl , fn , fn ),	\ |
| 119 | 	 __tg_generic_full(y, cfnl, cfn , cfnf, fnl , fn , fnf ))	\ |
| 120 | 	 (__VA_ARGS__) |
| 121 | #else |
| 122 | #error "<tgmath.h> not implemented for this compiler" |
| 123 | #endif |
| 124 | |
| 125 | /* Macros to save lots of repetition below */ |
| 126 | #define	__tg_simple(x, fn)						\ |
| 127 | 	__tg_impl_simple(x, x, x, fn##l, fn, fn##f, x) |
| 128 | #define	__tg_simple2(x, y, fn)						\ |
| 129 | 	__tg_impl_simple(x, x, y, fn##l, fn, fn##f, x, y) |
| 130 | #define	__tg_simple3(x, y, z, fn)					\ |
| 131 | 	__tg_impl_simple(x, y, z, fn##l, fn, fn##f, x, y, z) |
| 132 | #define	__tg_simplev(x, fn, ...)					\ |
| 133 | 	__tg_impl_simple(x, x, x, fn##l, fn, fn##f, __VA_ARGS__) |
| 134 | #define	__tg_full(x, fn)						\ |
| 135 | 	__tg_impl_full(x, x, c##fn##l, c##fn, c##fn##f, fn##l, fn, fn##f, x) |
| 136 | #define	__tg_full2(x, y, fn)						\ |
| 137 | 	__tg_impl_full(x, y, c##fn##l, c##fn, c##fn##f, fn##l, fn, fn##f, x, y) |
| 138 | |
| 139 | /* 7.22#4 -- These macros expand to real or complex functions, depending on |
| 140 | * the type of their arguments. */ |
| 141 | #define	acos(x)		__tg_full(x, acos) |
| 142 | #define	asin(x)		__tg_full(x, asin) |
| 143 | #define	atan(x)		__tg_full(x, atan) |
| 144 | #define	acosh(x)	__tg_full(x, acosh) |
| 145 | #define	asinh(x)	__tg_full(x, asinh) |
| 146 | #define	atanh(x)	__tg_full(x, atanh) |
| 147 | #define	cos(x)		__tg_full(x, cos) |
| 148 | #define	sin(x)		__tg_full(x, sin) |
| 149 | #define	tan(x)		__tg_full(x, tan) |
| 150 | #define	cosh(x)		__tg_full(x, cosh) |
| 151 | #define	sinh(x)		__tg_full(x, sinh) |
| 152 | #define	tanh(x)		__tg_full(x, tanh) |
| 153 | #define	exp(x)		__tg_full(x, exp) |
| 154 | #define	log(x)		__tg_full(x, log) |
| 155 | #define	pow(x, y)	__tg_full2(x, y, pow) |
| 156 | #define	sqrt(x)		__tg_full(x, sqrt) |
| 157 | |
| 158 | /* "The corresponding type-generic macro for fabs and cabs is fabs." */ |
| 159 | #define	fabs(x)		__tg_impl_full(x, x, cabsl, cabs, cabsf,	\ |
| 160 | 			 fabsl, fabs, fabsf, x) |
| 161 | |
| 162 | /* 7.22#5 -- These macros are only defined for arguments with real type. */ |
| 163 | #define	atan2(x, y)	__tg_simple2(x, y, atan2) |
| 164 | #define	cbrt(x)		__tg_simple(x, cbrt) |
| 165 | #define	ceil(x)		__tg_simple(x, ceil) |
| 166 | #define	copysign(x, y)	__tg_simple2(x, y, copysign) |
| 167 | #define	erf(x)		__tg_simple(x, erf) |
| 168 | #define	erfc(x)		__tg_simple(x, erfc) |
| 169 | #define	exp2(x)		__tg_simple(x, exp2) |
| 170 | #define	expm1(x)	__tg_simple(x, expm1) |
| 171 | #define	fdim(x, y)	__tg_simple2(x, y, fdim) |
| 172 | #define	floor(x)	__tg_simple(x, floor) |
| 173 | #define	fma(x, y, z)	__tg_simple3(x, y, z, fma) |
| 174 | #define	fmax(x, y)	__tg_simple2(x, y, fmax) |
| 175 | #define	fmin(x, y)	__tg_simple2(x, y, fmin) |
| 176 | #define	fmod(x, y)	__tg_simple2(x, y, fmod) |
| 177 | #define	frexp(x, y)	__tg_simplev(x, frexp, x, y) |
| 178 | #define	hypot(x, y)	__tg_simple2(x, y, hypot) |
| 179 | #define	ilogb(x)	__tg_simple(x, ilogb) |
| 180 | #define	ldexp(x, y)	__tg_simplev(x, ldexp, x, y) |
| 181 | #define	lgamma(x)	__tg_simple(x, lgamma) |
| 182 | #define	llrint(x)	__tg_simple(x, llrint) |
| 183 | #define	llround(x)	__tg_simple(x, llround) |
| 184 | #define	log10(x)	__tg_simple(x, log10) |
| 185 | #define	log1p(x)	__tg_simple(x, log1p) |
| 186 | #define	log2(x)		__tg_simple(x, log2) |
| 187 | #define	logb(x)		__tg_simple(x, logb) |
| 188 | #define	lrint(x)	__tg_simple(x, lrint) |
| 189 | #define	lround(x)	__tg_simple(x, lround) |
| 190 | #define	nearbyint(x)	__tg_simple(x, nearbyint) |
| 191 | #define	nextafter(x, y)	__tg_simple2(x, y, nextafter) |
| 192 | #define	nexttoward(x, y) __tg_simplev(x, nexttoward, x, y) |
| 193 | #define	remainder(x, y)	__tg_simple2(x, y, remainder) |
| 194 | #define	remquo(x, y, z)	__tg_impl_simple(x, x, y, remquol, remquo,	\ |
| 195 | 			 remquof, x, y, z) |
| 196 | #define	rint(x)		__tg_simple(x, rint) |
| 197 | #define	round(x)	__tg_simple(x, round) |
| 198 | #define	scalbn(x, y)	__tg_simplev(x, scalbn, x, y) |
| 199 | #define	scalbln(x, y)	__tg_simplev(x, scalbln, x, y) |
| 200 | #define	tgamma(x)	__tg_simple(x, tgamma) |
| 201 | #define	trunc(x)	__tg_simple(x, trunc) |
| 202 | |
| 203 | /* 7.22#6 -- These macros always expand to complex functions. */ |
| 204 | #define	carg(x)		__tg_simple(x, carg) |
| 205 | #define	cimag(x)	__tg_simple(x, cimag) |
| 206 | #define	conj(x)		__tg_simple(x, conj) |
| 207 | #define	cproj(x)	__tg_simple(x, cproj) |
| 208 | #define	creal(x)	__tg_simple(x, creal) |
| 209 | |
| 210 | #endif /* !_TGMATH_H_ */ |