<tgmath.h>
Stefan Farfeleder
stefan at fafoe.narf.at
Thu Apr 29 13:33:21 PDT 2004
Hi,
here's an implementation of the C99 header <tgmath.h>. The macros
cimag, cimagf, creal and crealf are currently conflicting with the ones
from <complex.h>.
Cheers,
Stefan
-------------- next part --------------
/*-
* Copyright (c) 2004 Stefan Farfeleder.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _TGMATH_H_
#define _TGMATH_H_
#include <complex.h>
#include <math.h>
extern double __tg_d;
extern long double __tg_ld;
extern complex float __tg_cf;
extern complex double __tg_cd;
extern complex long double __tg_cld;
/*
* We require three magic predicates to be available.
*
* - __tg_same_type(exp1, exp2) returns 1 if the expressions exp1 and exp2
* have the same type, 0 otherwise. Neither expression shall be evaluated.
* - __tg_integer_type(exp) returns 1 if the expression exp has integer type,
* 0 otherwise. exp shall not be evaluated.
* - __tg_cond_expr(c, exp1, exp2) returns exp1 if c evaluates to
* non-zero, exp2 otherwise. Note that exp1's and exp2's types must not
* be converted (like ?: does).
*/
#ifdef __GNUC__
#define __tg_same_type(e1, e2) \
__builtin_types_compatible_p(__typeof__(e1), __typeof__(e2))
#define __tg_integer_type(e) ((__typeof__(e))1.5 == 1)
#define __tg_cond_expr(c, e1, e2) __builtin_choose_expr(c, e1, e2)
#else
#error "need compiler support for __tg_same_type(), __tg_integer_type() and __tg_cond_expr()"
#endif
#define __tg_use_long(x) \
(__tg_same_type(x, __tg_ld) || __tg_same_type(x, __tg_cld))
#define __tg_use_long2(x, y) (__tg_use_long(x) || __tg_use_long(y))
#define __tg_use_double(x) \
(__tg_same_type(x, __tg_d) || __tg_same_type(x, __tg_cd) || \
__tg_integer_type(x))
#define __tg_use_double2(x, y) (__tg_use_double(x) || __tg_use_double(y))
#define __tg_use_complex(x) \
(__tg_same_type(x, __tg_cf) || __tg_same_type(x, __tg_cd) || \
__tg_same_type(x, __tg_cld))
#define __tg_fnv(x, fn, ...) \
__tg_cond_expr(__tg_use_long(x), fn##l(__VA_ARGS__), \
__tg_cond_expr(__tg_use_double(x), fn(__VA_ARGS__), \
fn##f(__VA_ARGS__)))
#define __tg_fn(x, fn) __tg_fnv(x, fn, x)
#define __tg_fn2v(x, y, fn, ...) \
__tg_cond_expr(__tg_use_long2(x, y), fn##l(__VA_ARGS__), \
__tg_cond_expr(__tg_use_double2(x, y), fn(__VA_ARGS__), \
fn##f(__VA_ARGS__)))
#define __tg_fn2(x, y, fn) __tg_fn2v(x, y, fn, x, y)
#define __tg_fn3(x, y, z, fn) \
__tg_cond_expr(__tg_use_long2(x, y) || __tg_use_long(z), \
fn##l(x, y, z), __tg_cond_expr(__tg_use_double2(x, y) || \
__tg_use_double(z), fn(x, y, z), fn##f(x, y, z)))
#define __tg_fn_both(x, fn) \
__tg_cond_expr(__tg_use_complex(x), __tg_fn(x, c##fn), __tg_fn(x, fn))
#define __tg_fn_both2(x, y, fn) \
__tg_cond_expr(__tg_use_complex(x) || __tg_use_complex(y), \
__tg_fn2(x, y, c##fn), __tg_fn2(x, y, fn))
/* 7.22#4 */
#define acos(x) __tg_fn_both(x, acos)
#define asin(x) __tg_fn_both(x, asin)
#define atan(x) __tg_fn_both(x, atan)
#define acosh(x) __tg_fn_both(x, acosh)
#define asinh(x) __tg_fn_both(x, asinh)
#define atanh(x) __tg_fn_both(x, atanh)
#define cos(x) __tg_fn_both(x, cos)
#define sin(x) __tg_fn_both(x, sin)
#define tan(x) __tg_fn_both(x, tan)
#define cosh(x) __tg_fn_both(x, cosh)
#define sinh(x) __tg_fn_both(x, sinh)
#define tanh(x) __tg_fn_both(x, tanh)
#define exp(x) __tg_fn_both(x, exp)
#define log(x) __tg_fn_both(x, log)
#define pow(x, y) __tg_fn_both2(x, y, pow)
#define sqrt(x) __tg_fn_both(x, sqrt)
/* "The corresponding type-generic macro for fabs and cabs is fabs." */
#define fabs(x) __tg_cond_expr(__tg_use_complex(x), \
__tg_fn(x, cabs), __tg_fn(x, fabs))
/* 7.22#5 */
#define atan2(x, y) __tg_fn2(x, y, atan2)
#define cbrt(x) __tg_fn(x, cbrt)
#define ceil(x) __tg_fn(x, ceil)
#define copysign(x, y) __tg_fn2(x, y, copysign)
#define erf(x) __tg_fn(x, erf)
#define erfc(x) __tg_fn(x, erfc)
#define exp2(x) __tg_fn(x, exp2)
#define expm1(x) __tg_fn(x, expm1)
#define fdim(x, y) __tg_fn2(x, y, fdim)
#define floor(x) __tg_fn(x, floor)
#define fma(x, y, z) __tg_fn3(x, y, z, fma)
#define fmax(x, y) __tg_fn2(x, y, fmax)
#define fmin(x, y) __tg_fn2(x, y, fmin)
#define fmod(x, y) __tg_fn2(x, y, fmod)
#define frexp(x, y) __tg_fnv(x, frexp, x, y)
#define hypot(x, y) __tg_fn2(x, y, hypot)
#define ilogb(x) __tg_fn(x, ilogb)
#define ldexp(x, y) __tg_fnv(x, ldexp, x, y)
#define lgamma(x) __tg_fn(x, lgamma)
#define llrint(x) __tg_fn(x, llrint)
#define llround(x) __tg_fn(x, llround)
#define log10(x) __tg_fn(x, log10)
#define log1p(x) __tg_fn(x, log1p)
#define log2(x) __tg_fn(x, log2)
#define logb(x) __tg_fn(x, logb)
#define lrint(x) __tg_fn(x, lrint)
#define lround(x) __tg_fn(x, lround)
#define nextbyint(x) __tg_fn(x, nextbyint)
#define nextafter(x, y) __tg_fn2(x, y, nextafter)
#define nexttoward(x, y) __tg_fnv(x, nexttoward, x, y)
#define remainder(x, y) __tg_fn2(x, y, remainder)
#define remquo(x, y, z) __tg_fn2v(x, y, remquo, x, y, z)
#define rint(x) __tg_fn(x, rint)
#define round(x) __tg_fn(x, round)
#define scalbn(x, y) __tg_fnv(x, scalbn, x, y)
#define scalbln(x, y) __tg_fnv(x, scalbln, x, y)
#define tgamma(x) __tg_fn(x, tgamma)
#define trunc(x) __tg_fn(x, trunc)
/* 7.22#6 */
#define carg(x) __tg_fn(x, carg)
#define cimag(x) __tg_fn(x, cimag)
#define conj(x) __tg_fn(x, conj)
#define cproj(x) __tg_fn(x, cproj)
#define creal(x) __tg_fn(x, creal)
#endif /* !_TGMATH_H_ */
More information about the freebsd-standards
mailing list