From owner-freebsd-numerics@FreeBSD.ORG Tue May 28 04:32:24 2013 Return-Path: Delivered-To: freebsd-numerics@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 016CACE2; Tue, 28 May 2013 04:32:24 +0000 (UTC) (envelope-from das@freebsd.org) Received: from zim.MIT.EDU (50-196-151-174-static.hfc.comcastbusiness.net [50.196.151.174]) by mx1.freebsd.org (Postfix) with ESMTP id D776875B; Tue, 28 May 2013 04:32:23 +0000 (UTC) Received: from zim.MIT.EDU (localhost [127.0.0.1]) by zim.MIT.EDU (8.14.7/8.14.2) with ESMTP id r4S4W8sJ012895; Mon, 27 May 2013 21:32:08 -0700 (PDT) (envelope-from das@freebsd.org) Received: (from das@localhost) by zim.MIT.EDU (8.14.7/8.14.2/Submit) id r4S4W5tG012894; Mon, 27 May 2013 21:32:05 -0700 (PDT) (envelope-from das@freebsd.org) Date: Mon, 27 May 2013 21:32:05 -0700 From: David Schultz To: Stephen Montgomery-Smith Subject: Re: Use of C99 extra long double math functions after r236148 Message-ID: <20130528043205.GA3282@zim.MIT.EDU> References: <500DAD41.5030104@missouri.edu> <20120724113214.G934@besplex.bde.org> <501204AD.30605@missouri.edu> <20120727032611.GB25690@server.rulingia.com> <20120728125824.GA26553@server.rulingia.com> <501460BB.30806@missouri.edu> <20120728231300.GA20741@server.rulingia.com> <50148F02.4020104@missouri.edu> <20120729222706.GA29048@server.rulingia.com> <5015BB9F.90807@missouri.edu> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5015BB9F.90807@missouri.edu> X-Mailman-Approved-At: Tue, 28 May 2013 11:20:14 +0000 Cc: Diane Bruce , Bruce Evans , John Baldwin , David Chisnall , freebsd-numerics@freebsd.org, Bruce Evans , Steve Kargl , Peter Jeremy , Warner Losh X-BeenThere: freebsd-numerics@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Discussions of high quality implementation of libm functions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 May 2013 04:32:24 -0000 On Sun, Jul 29, 2012, Stephen Montgomery-Smith wrote: > Also I forgot that the real part of casinh(0+I*x) isn't always 0. If > |x|>1, it is something non-zero. And so you need to check that > creal(casinh(0+I*x)) and creal(casinh(-0+I*x)) have opposite signs in > this case. > > > I'm less sure of the next logical > > step, which is to check things like > > casinh(x + I*0) = asinh(x) + I*0 > > Does C99 mandate this? My programs probably won't satisfy this, because > I realized that the computation works in these cases anyway. Of course, > it would be easy to make it happen. Hi Stephen, I wrote some tests to cover the corner cases for the complex inverse trig functions. They don't find any nontrivial bugs in your implementations. :-) Now that you have a commit bit, would you like to commit your code, or shall I? Below is a diff of all the changes needed to integrate it. I have a short list of style fixes, but otherwise I think what you have is good: - wrap lines to 80 chars, please - spaces between operators - "static inline", not "inline static" - don't use "inline" on large functions Index: lib/msun/Makefile =================================================================== --- lib/msun/Makefile (revision 251024) +++ lib/msun/Makefile (working copy) @@ -105,7 +105,8 @@ .endif # C99 complex functions -COMMON_SRCS+= s_ccosh.c s_ccoshf.c s_cexp.c s_cexpf.c \ +COMMON_SRCS+= catrig.c catrigf.c \ + s_ccosh.c s_ccoshf.c s_cexp.c s_cexpf.c \ s_cimag.c s_cimagf.c s_cimagl.c \ s_conj.c s_conjf.c s_conjl.c \ s_cproj.c s_cprojf.c s_creal.c s_crealf.c s_creall.c \ @@ -126,7 +127,7 @@ INCS+= fenv.h math.h MAN= acos.3 acosh.3 asin.3 asinh.3 atan.3 atan2.3 atanh.3 \ - ceil.3 ccos.3 ccosh.3 cexp.3 \ + ceil.3 cacos.3 ccos.3 ccosh.3 cexp.3 \ cimag.3 copysign.3 cos.3 cosh.3 csqrt.3 erf.3 exp.3 fabs.3 fdim.3 \ feclearexcept.3 feenableexcept.3 fegetenv.3 \ fegetround.3 fenv.3 floor.3 \ @@ -144,6 +145,9 @@ MLINKS+=atanh.3 atanhf.3 MLINKS+=atan2.3 atan2f.3 atan2.3 atan2l.3 \ atan2.3 carg.3 atan2.3 cargf.3 atan2.3 cargl.3 +MLINKS+=cacos.3 cacosf.3 cacos.3 cacosh.3 cacos.3 cacoshf.3 \ + cacos.3 casin.3 cacos.3 casinf.3 cacos.3 casinh.3 cacos.3 casinhf.3 \ + cacos.3 catan.3 cacos.3 catanf.3 cacos.3 catanh.3 cacos.3 catanhf.3 MLINKS+=ccos.3 ccosf.3 ccos.3 csin.3 ccos.3 csinf.3 ccos.3 ctan.3 ccos.3 ctanf.3 MLINKS+=ccosh.3 ccoshf.3 ccosh.3 csinh.3 ccosh.3 csinhf.3 \ ccosh.3 ctanh.3 ccosh.3 ctanhf.3 Index: lib/msun/Symbol.map =================================================================== --- lib/msun/Symbol.map (revision 251024) +++ lib/msun/Symbol.map (working copy) @@ -237,6 +237,18 @@ fegetround; fesetround; fesetenv; + cacos; + cacosf; + cacosh; + cacoshf; + casin; + casinf; + casinh; + casinhf; + catan; + catanf; + catanh; + catanhf; csin; csinf; csinh; Index: lib/msun/man/cacos.3 =================================================================== --- lib/msun/man/cacos.3 (revision 0) +++ lib/msun/man/cacos.3 (working copy) @@ -0,0 +1,128 @@ +.\" Copyright (c) 2013 David Schultz +.\" 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$ +.\" +.Dd May 27, 2013 +.Dt CACOS 3 +.Os +.Sh NAME +.Nm cacos , +.Nm cacosf , +.Nm cacosh , +.Nm cacoshf , +.Nm casin , +.Nm casinf +.Nm casinh , +.Nm casinhf +.Nm catan , +.Nm catanf +.Nm catanh , +.Nm catanhf +.Nd complex arc trigonometric and hyperbolic functions +.Sh LIBRARY +.Lb libm +.Sh SYNOPSIS +.In complex.h +.Ft double complex +.Fn cacos "double complex z" +.Ft float complex +.Fn cacosf "float complex z" +.Ft double complex +.Fn cacosh "double complex z" +.Ft float complex +.Fn cacoshf "float complex z" +.Ft double complex +.Fn casin "double complex z" +.Ft float complex +.Fn casinf "float complex z" +.Ft double complex +.Fn casinh "double complex z" +.Ft float complex +.Fn casinhf "float complex z" +.Ft double complex +.Fn catan "double complex z" +.Ft float complex +.Fn catanf "float complex z" +.Ft double complex +.Fn catanh "double complex z" +.Ft float complex +.Fn catanhf "float complex z" +.Sh DESCRIPTION +The +.Fn cacos , +.Fn casin , +and +.Fn catan +functions compute the principal value of the inverse cosine, sine, +and tangent of the complex number +.Fa z , +respectively. +The +.Fn cacosh , +.Fn casinh , +and +.Fn catanh +functions compute the principal value of the inverse hyperbolic +cosine, sine, and tangent, respectively. +The +.Fn cacosf , +.Fn casinf , +.Fn catanf +.Fn cacoshf , +.Fn casinhf , +and +.Fn catanhf +functions perform the same operations in +.Fa float +precision. +.Pp +.ie '\*[.T]'utf8' +. ds Un \[cu] +.el +. ds Un U +. +There is no universal convention for defining the principal values of +these functions. The following table gives the branch cuts, and the +corresponding ranges for the return values, adopted by the C language. +.Bl -column ".Sy Function" ".Sy (-\*(If*I, -I) \*(Un (I, \*(If*I)" ".Sy [-\*(Pi/2*I, \*(Pi/2*I]" +.It Sy Function Ta Sy Branch Cut(s) Ta Sy Range +.It cacos Ta (-\*(If, -1) \*(Un (1, \*(If) Ta [0, \*(Pi] +.It casin Ta (-\*(If, -1) \*(Un (1, \*(If) Ta [-\*(Pi/2, \*(Pi/2] +.It catan Ta (-\*(If*I, -i) \*(Un (I, \*(If*I) Ta [-\*(Pi/2, \*(Pi/2] +.It cacosh Ta (-\*(If, 1) Ta [-\*(Pi*I, \*(Pi*I] +.It casinh Ta (-\*(If*I, -i) \*(Un (I, \*(If*I) Ta [-\*(Pi/2*I, \*(Pi/2*I] +.It catanh Ta (-\*(If, -1) \*(Un (1, \*(If) Ta [-\*(Pi/2*I, \*(Pi/2*I] +.El +.Sh SEE ALSO +.Xr cacosh 3 , +.Xr ccosh 3 , +.Xr complex 3 , +.Xr cos 3 , +.Xr math 3 , +.Xr sin 3 , +.Xr tan 3 +.Sh STANDARDS +These functions conform to +.St -isoC-99 . Property changes on: lib/msun/man/cacos.3 ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: lib/msun/man/ccos.3 =================================================================== --- lib/msun/man/ccos.3 (revision 251024) +++ lib/msun/man/ccos.3 (working copy) @@ -69,6 +69,7 @@ .Fa float precision. .Sh SEE ALSO +.Xr cacos 3 , .Xr ccosh 3 , .Xr complex 3 , .Xr cos 3 , Index: lib/msun/man/ccosh.3 =================================================================== --- lib/msun/man/ccosh.3 (revision 251024) +++ lib/msun/man/ccosh.3 (working copy) @@ -69,6 +69,7 @@ .Fa float precision. .Sh SEE ALSO +.Xr cacosh 3 , .Xr ccos 3 , .Xr complex 3 , .Xr cosh 3 , Index: lib/msun/man/complex.3 =================================================================== --- lib/msun/man/complex.3 (revision 251024) +++ lib/msun/man/complex.3 (working copy) @@ -89,6 +89,12 @@ .\" Section 7.3.5-6 of ISO C99 standard .Ss Trigonometric and Hyperbolic Functions .Cl +cacos arc cosine +cacosh arc hyperbolic cosine +casin arc sine +casinh arc hyperbolic sine +catan arc tangent +catanh arc hyperbolic tangent ccos cosine ccosh hyperbolic cosine csin sine @@ -111,20 +117,8 @@ functions described here conform to .St -isoC-99 . .Sh BUGS -The inverse trigonometric and hyperbolic functions -.Fn cacos , -.Fn cacosh , -.Fn casin , -.Fn casinh , -.Fn catan , -and -.Fn catanh -are not implemented. -.Pp The logarithmic functions .Fn clog -are not implemented. -.Pp -The power functions +and the power functions .Fn cpow are not implemented. Index: tools/regression/lib/msun/Makefile =================================================================== --- tools/regression/lib/msun/Makefile (revision 251024) +++ tools/regression/lib/msun/Makefile (working copy) @@ -2,7 +2,8 @@ TESTS= test-cexp test-conj test-csqrt test-ctrig \ test-exponential test-fenv test-fma \ - test-fmaxmin test-ilogb test-invtrig test-logarithm test-lrint \ + test-fmaxmin test-ilogb test-invtrig test-invctrig \ + test-logarithm test-lrint \ test-lround test-nan test-nearbyint test-next test-rem test-trig CFLAGS+= -O0 -lm Index: tools/regression/lib/msun/test-invctrig.c =================================================================== --- tools/regression/lib/msun/test-invctrig.c (revision 0) +++ tools/regression/lib/msun/test-invctrig.c (working copy) @@ -0,0 +1,467 @@ +/*- + * Copyright (c) 2008-2013 David Schultz + * 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. + */ + +/* + * Tests for casin[h](), cacos[h](), and catan[h](). + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ + FE_OVERFLOW | FE_UNDERFLOW) +#define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) +#define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) +#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) +#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) +#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) + +#pragma STDC FENV_ACCESS ON +#pragma STDC CX_LIMITED_RANGE OFF + +/* + * XXX gcc implements complex multiplication incorrectly. In + * particular, it implements it as if the CX_LIMITED_RANGE pragma + * were ON. Consequently, we need this function to form numbers + * such as x + INFINITY * I, since gcc evalutes INFINITY * I as + * NaN + INFINITY * I. + */ +static inline long double complex +cpackl(long double x, long double y) +{ + long double complex z; + + __real__ z = x; + __imag__ z = y; + return (z); +} + +/* Flags that determine whether to check the signs of the result. */ +#define CS_REAL 1 +#define CS_IMAG 2 +#define CS_BOTH (CS_REAL | CS_IMAG) + +#ifdef DEBUG +#define debug(...) printf(__VA_ARGS__) +#else +#define debug(...) (void)0 +#endif + +/* + * Test that a function returns the correct value and sets the + * exception flags correctly. The exceptmask specifies which + * exceptions we should check. We need to be lenient for several + * reasons, but mainly because on some architectures it's impossible + * to raise FE_OVERFLOW without raising FE_INEXACT. + * + * These are macros instead of functions so that assert provides more + * meaningful error messages. + * + * XXX The volatile here is to avoid gcc's bogus constant folding and work + * around the lack of support for the FENV_ACCESS pragma. + */ +#define test_p(func, z, result, exceptmask, excepts, checksign) do { \ + volatile long double complex _d = z; \ + debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ + creall(_d), cimagl(_d), creall(result), cimagl(result)); \ + assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ + assert(cfpequal((func)(_d), (result), (checksign))); \ + assert(((func), fetestexcept(exceptmask) == (excepts))); \ +} while (0) + +/* + * Test within a given tolerance. The tolerance indicates relative error + * in ulps. + */ +#define test_p_tol(func, z, result, tol) do { \ + volatile long double complex _d = z; \ + debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ + creall(_d), cimagl(_d), creall(result), cimagl(result)); \ + assert(cfpequal_tol((func)(_d), (result), (tol))); \ +} while (0) + +/* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ +#define test(func, z, result, exceptmask, excepts, checksign) do { \ + test_p(func, z, result, exceptmask, excepts, checksign); \ + test_p(func, conjl(z), conjl(result), exceptmask, excepts, checksign); \ +} while (0) +#define test_tol(func, z, result, tol) do { \ + test_p_tol(func, z, result, tol); \ + test_p_tol(func, conjl(z), conjl(result), tol); \ +} while (0) + +/* Test the given function in all precisions. */ +#define testall(func, x, result, exceptmask, excepts, checksign) do { \ + test(func, x, result, exceptmask, excepts, checksign); \ + test(func##f, x, result, exceptmask, excepts, checksign); \ +} while (0) +#define testall_odd(func, x, result, exceptmask, excepts, checksign) do { \ + testall(func, x, result, exceptmask, excepts, checksign); \ + testall(func, -(x), -result, exceptmask, excepts, checksign); \ +} while (0) +#define testall_even(func, x, result, exceptmask, excepts, checksign) do { \ + testall(func, x, result, exceptmask, excepts, checksign); \ + testall(func, -(x), result, exceptmask, excepts, checksign); \ +} while (0) + +/* + * Test the given function in all precisions, within a given tolerance. + * The tolerance is specified in ulps. + */ +#define testall_tol(func, x, result, tol) do { \ + test_tol(func, x, result, (tol) * DBL_ULP()); \ + test_tol(func##f, x, result, (tol) * FLT_ULP()); \ +} while (0) +#define testall_odd_tol(func, x, result, tol) do { \ + testall_tol(func, x, result, tol); \ + testall_tol(func, -(x), -result, tol); \ +} while (0) +#define testall_even_tol(func, x, result, tol) do { \ + testall_tol(func, x, result, tol); \ + testall_tol(func, -(x), result, tol); \ +} while (0) + +static const long double +pi = 3.14159265358979323846264338327950280L, +c3pi = 9.42477796076937971538793014983850839L; + +/* + * Determine whether x and y are equal, with two special rules: + * +0.0 != -0.0 + * NaN == NaN + * If checksign is 0, we compare the absolute values instead. + */ +static int +fpequal(long double x, long double y, int checksign) +{ + if (isnan(x) && isnan(y)) + return (1); + if (checksign) + return (x == y && !signbit(x) == !signbit(y)); + else + return (fabsl(x) == fabsl(y)); +} + +static int +fpequal_tol(long double x, long double y, long double tol) +{ + fenv_t env; + int ret; + + if (isnan(x) && isnan(y)) + return (1); + if (!signbit(x) != !signbit(y)) + return (0); + if (x == y) + return (1); + if (tol == 0 || y == 0.0) + return (0); + + /* Hard case: need to check the tolerance. */ + feholdexcept(&env); + ret = fabsl(x - y) <= fabsl(y * tol); + fesetenv(&env); + return (ret); +} + +static int +cfpequal(long double complex x, long double complex y, int checksign) +{ + return (fpequal(creal(x), creal(y), checksign & CS_REAL) + && fpequal(cimag(x), cimag(y), checksign & CS_IMAG)); +} + +static int +cfpequal_tol(long double complex x, long double complex y, long double tol) +{ + return (fpequal_tol(creal(x), creal(y), tol) + && fpequal_tol(cimag(x), cimag(y), tol)); +} + + +/* Tests for 0 */ +void +test_zero(void) +{ + long double complex zero = cpackl(0.0, 0.0); + + testall_tol(cacosh, zero, cpackl(0.0, pi / 2), 1); + testall_tol(cacosh, -zero, cpackl(0.0, -pi / 2), 1); + testall_tol(cacos, zero, cpackl(pi / 2, -0.0), 1); + testall_tol(cacos, -zero, cpackl(pi / 2, 0.0), 1); + + testall_odd(casinh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); + testall_odd(casin, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); + + testall_odd(catanh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); + testall_odd(catan, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); +} + +/* + * Tests for NaN inputs. + */ +void +test_nan() +{ + long double complex nan_nan = cpackl(NAN, NAN); + long double complex z; + + /* + * IN CACOSH CACOS CASINH CATANH + * NaN,NaN NaN,NaN NaN,NaN NaN,NaN NaN,NaN + * finite,NaN NaN,NaN* NaN,NaN* NaN,NaN* NaN,NaN* + * NaN,finite NaN,NaN* NaN,NaN* NaN,NaN* NaN,NaN* + * NaN,Inf Inf,NaN NaN,-Inf ?Inf,NaN ?0,pi/2 + * +-Inf,NaN Inf,NaN NaN,?Inf +-Inf,NaN +-0,NaN + * +-0,NaN NaN,NaN* pi/2,NaN NaN,NaN* +-0,NaN + * NaN,0 NaN,NaN* NaN,NaN* NaN,0 NaN,NaN* + * + * * = raise invalid + */ + z = nan_nan; + testall(cacosh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(cacos, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(casinh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(casin, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(catanh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(catan, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + + z = cpackl(0.5, NAN); + testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); + testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); + testall(casinh, z, nan_nan, OPT_INVALID, 0, 0); + testall(casin, z, nan_nan, OPT_INVALID, 0, 0); + testall(catanh, z, nan_nan, OPT_INVALID, 0, 0); + testall(catan, z, nan_nan, OPT_INVALID, 0, 0); + + z = cpackl(NAN, 0.5); + testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); + testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); + testall(casinh, z, nan_nan, OPT_INVALID, 0, 0); + testall(casin, z, nan_nan, OPT_INVALID, 0, 0); + testall(catanh, z, nan_nan, OPT_INVALID, 0, 0); + testall(catan, z, nan_nan, OPT_INVALID, 0, 0); + + z = cpackl(NAN, INFINITY); + testall(cacosh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall(cacosh, -z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall(cacos, z, cpackl(NAN, -INFINITY), ALL_STD_EXCEPT, 0, CS_IMAG); + testall(casinh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); + testall(casin, z, cpackl(NAN, INFINITY), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_tol(catanh, z, cpackl(0.0, pi / 2), 1); + testall(catan, z, cpackl(NAN, 0.0), ALL_STD_EXCEPT, 0, CS_IMAG); + + z = cpackl(INFINITY, NAN); + testall_even(cacosh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, + CS_REAL); + testall_even(cacos, z, cpackl(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); + testall_odd(casinh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, + CS_REAL); + testall_odd(casin, z, cpackl(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); + testall_odd(catanh, z, cpackl(0.0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd_tol(catan, z, cpackl(pi / 2, 0.0), 1); + + z = cpackl(0.0, NAN); + /* XXX We allow a spurious inexact exception here. */ + testall_even(cacosh, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); + testall_even_tol(cacos, z, cpackl(pi / 2, NAN), 1); + testall_odd(casinh, z, nan_nan, OPT_INVALID, 0, 0); + testall_odd(casin, z, cpackl(0.0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(catanh, z, cpackl(0.0, NAN), OPT_INVALID, 0, CS_REAL); + testall_odd(catan, z, nan_nan, OPT_INVALID, 0, 0); + + z = cpackl(NAN, 0.0); + testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); + testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); + testall(casinh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); + testall(casin, z, nan_nan, OPT_INVALID, 0, 0); + testall(catanh, z, nan_nan, OPT_INVALID, 0, CS_IMAG); + testall(catan, z, cpackl(NAN, 0.0), ALL_STD_EXCEPT, 0, 0); +} + +void +test_inf(void) +{ + long double complex z; + + /* + * IN CACOSH CACOS CASINH CATANH + * Inf,Inf Inf,pi/4 pi/4,-Inf Inf,pi/4 0,pi/2 + * -Inf,Inf Inf,3pi/4 3pi/4,-Inf --- --- + * Inf,finite Inf,0 0,-Inf Inf,0 0,pi/2 + * -Inf,finite Inf,pi pi,-Inf --- --- + * finite,Inf Inf,pi/2 pi/2,-Inf Inf,pi/2 0,pi/2 + */ + z = cpackl(INFINITY, INFINITY); + testall_tol(cacosh, z, cpackl(INFINITY, pi / 4), 1); + testall_tol(cacosh, -z, cpackl(INFINITY, -c3pi / 4), 1); + testall_tol(cacos, z, cpackl(pi / 4, -INFINITY), 1); + testall_tol(cacos, -z, cpackl(c3pi / 4, INFINITY), 1); + testall_odd_tol(casinh, z, cpackl(INFINITY, pi / 4), 1); + testall_odd_tol(casin, z, cpackl(pi / 4, INFINITY), 1); + testall_odd_tol(catanh, z, cpackl(0, pi / 2), 1); + testall_odd_tol(catan, z, cpackl(pi / 2, 0), 1); + + z = cpackl(INFINITY, 0.5); + /* XXX We allow a spurious inexact exception here. */ + testall(cacosh, z, cpackl(INFINITY, 0), OPT_INEXACT, 0, CS_BOTH); + testall_tol(cacosh, -z, cpackl(INFINITY, -pi), 1); + testall(cacos, z, cpackl(0, -INFINITY), OPT_INEXACT, 0, CS_BOTH); + testall_tol(cacos, -z, cpackl(pi, INFINITY), 1); + testall_odd(casinh, z, cpackl(INFINITY, 0), OPT_INEXACT, 0, CS_BOTH); + testall_odd_tol(casin, z, cpackl(pi / 2, INFINITY), 1); + testall_odd_tol(catanh, z, cpackl(0, pi / 2), 1); + testall_odd_tol(catan, z, cpackl(pi / 2, 0), 1); + + z = cpackl(0.5, INFINITY); + testall_tol(cacosh, z, cpackl(INFINITY, pi / 2), 1); + testall_tol(cacosh, -z, cpackl(INFINITY, -pi / 2), 1); + testall_tol(cacos, z, cpackl(pi / 2, -INFINITY), 1); + testall_tol(cacos, -z, cpackl(pi / 2, INFINITY), 1); + testall_odd_tol(casinh, z, cpackl(INFINITY, pi / 2), 1); + /* XXX We allow a spurious inexact exception here. */ + testall_odd(casin, z, cpackl(0.0, INFINITY), OPT_INEXACT, 0, CS_BOTH); + testall_odd_tol(catanh, z, cpackl(0, pi / 2), 1); + testall_odd_tol(catan, z, cpackl(pi / 2, 0), 1); +} + +/* Tests along the real and imaginary axes. */ +void +test_axes(void) +{ + static const long double nums[] = { + -2, -1, -0.5, 0.5, 1, 2 + }; + long double complex z; + int i; + + for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { + /* Real axis */ + z = cpackl(nums[i], 0.0); + if (fabs(nums[i]) <= 1) { + testall_tol(cacosh, z, cpackl(0.0, acos(nums[i])), 1); + testall_tol(cacos, z, cpackl(acosl(nums[i]), -0.0), 1); + testall_tol(casin, z, cpackl(asinl(nums[i]), 0.0), 1); + testall_tol(catanh, z, cpackl(atanh(nums[i]), 0.0), 1); + } else { + testall_tol(cacosh, z, + cpackl(acosh(fabs(nums[i])), + (nums[i] < 0) ? pi : 0), 1); + testall_tol(cacos, z, + cpackl((nums[i] < 0) ? pi : 0, + -acosh(fabs(nums[i]))), 1); + testall_tol(casin, z, + cpackl(copysign(pi / 2, nums[i]), + acosh(fabs(nums[i]))), 1); + testall_tol(catanh, z, + cpackl(atanh(1 / nums[i]), pi / 2), 1); + } + testall_tol(casinh, z, cpackl(asinh(nums[i]), 0.0), 1); + testall_tol(catan, z, cpackl(atan(nums[i]), 0), 1); + + /* TODO: Test the imaginary axis. */ + } +} + +void +test_small(void) +{ + /* + * z = 0.75 + i 0.25 + * acos(z) = Pi/4 - i ln(2)/2 + * asin(z) = Pi/4 + i ln(2)/2 + * atan(z) = atan(4)/2 + i ln(17/9)/4 + */ + static const struct { + long double a, b; + long double acos_a, acos_b; + long double asin_a, asin_b; + long double atan_a, atan_b; + } tests[] = { + { 0.75L, + 0.25L, + pi / 4, + -0.34657359027997265470861606072908828L, + pi / 4, + 0.34657359027997265470861606072908828L, + 0.66290883183401623252961960521423782L, + 0.15899719167999917436476103600701878L }, + }; + long double complex z; + int i; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + z = cpackl(tests[i].a, tests[i].b); + testall_tol(cacos, z, + cpackl(tests[i].acos_a, tests[i].acos_b), 2); + testall_odd_tol(casin, z, + cpackl(tests[i].asin_a, tests[i].asin_b), 2); + testall_odd_tol(catan, z, + cpackl(tests[i].atan_a, tests[i].atan_b), 2); + } +} + +/* Test inputs that might cause overflow in a sloppy implementation. */ +void +test_large(void) +{ + + /* TODO: Write these tests */ +} + +int +main(int argc, char *argv[]) +{ + + printf("1..6\n"); + + test_zero(); + printf("ok 1 - invctrig zero\n"); + + test_nan(); + printf("ok 2 - invctrig nan\n"); + + test_inf(); + printf("ok 3 - invctrig inf\n"); + + test_axes(); + printf("ok 4 - invctrig axes\n"); + + test_small(); + printf("ok 5 - invctrig small\n"); + + test_large(); + printf("ok 6 - invctrig large\n"); + + return (0); +} Property changes on: tools/regression/lib/msun/test-invctrig.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property