Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Sep 2012 23:32:34 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        Stephen Montgomery-Smith <stephen@missouri.edu>, freebsd-numerics@freebsd.org
Subject:   Re: Complex arg-trig functions
Message-ID:  <20120912225847.J1771@besplex.bde.org>
In-Reply-To: <20120912191556.F1078@besplex.bde.org>
References:  <5017111E.6060003@missouri.edu> <501C361D.4010807@missouri.edu> <20120804165555.X1231@besplex.bde.org> <501D51D7.1020101@missouri.edu> <20120805030609.R3101@besplex.bde.org> <501D9C36.2040207@missouri.edu> <20120805175106.X3574@besplex.bde.org> <501EC015.3000808@missouri.edu> <20120805191954.GA50379@troutmask.apl.washington.edu> <20120807205725.GA10572@server.rulingia.com> <20120809025220.N4114@besplex.bde.org> <5027F07E.9060409@missouri.edu> <20120814003614.H3692@besplex.bde.org> <50295F5C.6010800@missouri.edu> <20120814072946.S5260@besplex.bde.org> <50297CA5.5010900@missouri.edu> <50297E43.7090309@missouri.edu> <20120814201105.T934@besplex.bde.org> <502A780B.2010106@missouri.edu> <20120815223631.N1751@besplex.bde.org> <502C0CF8.8040003@missouri.edu> <20120906221028.O1542@besplex.bde.org> <5048D00B.8010401@missouri.edu> <504D3CCD.2050006@missouri.edu> <504FF726.9060001@missouri.edu> <20120912191556.F1078@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 12 Sep 2012, Bruce Evans wrote:

> Preliminary testing shows the following regressions relative to me previous
> fixed version.  (I got things like cacosh(NaN + I Inf) consistently wrong
> by classifying NaNs first, while not classifying NaNs first gets things
> like cacosh(NaN + I large) inconsistently wrong.)
> ...
> The huge errors for rcacos = realf(cacosf) etc. are sign errors for NaNs
> like the following:
>
> % x =                           0x4b000001 8388609
> % y =                           0xff800001 nan
> % rcacos(x, y) = 0xfff8000020000000 0xffc00001 nan
> % rcacosf(x, y) = 0x7ff8000020000000 0x7fc00001 nan
> % err = -0x8000000000000000 17179869184.00000
>
> rcacos() correctly preserves the sign of the NaN, but rcacosf() loses it
> iff |x| > 1 / FLT_EPSILON.  All of realf(clog_with_large_values()),
> realf(clogf()) and hypotf() seem never return a NaN with its sign bit set.
> This makes some sense for an real absolute value function but not for a
> complex function.  rcacos() loses the sign of the NaN similarly starting
> at 1 / DBL_EPSILON.

Fixes for this:

% diff -u2 catrig.c~ catrig.c
% --- catrig.c~	2012-09-12 02:43:28.000000000 +0000
% +++ catrig.c	2012-09-12 11:24:55.085541000 +0000
% @@ -31,7 +31,6 @@
%  #define ISINF(bx)	(((((bx).parts.msw & 0x7fffffff) - 0x7ff00000) | \
%  			(bx).parts.lsw) == 0)
% -#define ISFINITE(bx)	(((bx).parts.msw & 0x7ff00000) != 0x7ff00000)

Also, remove this again.

% 
% -#define FOUR_SQRT_MIN		1e-150	/* less than 4 / sqrt(DBL_MIN) */
% +#define FOUR_SQRT_MIN		1e-150	/* less than 4 * sqrt(DBL_MIN) */

Also, fix this comment.

%  #define FOURTH_SQRT_MAX		1e150	/* 1 / FOUR_SQRT_MIN */
% 
% @@ -281,16 +280,13 @@
%  	ay = fabs(y);
% 
% -	if (ax > 1/DBL_EPSILON || ay > 1/DBL_EPSILON)
% -		if (ISINF(bx) || ISINF(by) || (int)(1+tiny)==1) { /* raise inexact */
% -			if (SIGNBIT(bx) == 0)
% -				w = clog_for_large_values(z) + M_LN2;
% -			else
% -				w = clog_for_large_values(-z) + M_LN2;
% -			return (cpack(copysign(creal(w), x), copysign(cimag(w), y)));
% -		}
% -

Not actually changed -- obfuscated by diff.

%  	if (ISNAN(x) || ISNAN(y)) {
%  		/* casinh(NaN + I*0) = NaN + I*0 */
%  		if (y == 0) return (cpack(x+x, y));
% +		/* casinh(+-Inf + I*NaN) = +-Inf + I*NaN */
% +		if (ISINF(bx))
% +			return (cpack(x, y+y));
% +		/* casinh(NaN + I*+-Inf) = NaN +- I*Inf (sign now optional) */
% +		if (ISINF(by))
% +			return (cpack(y+y, x));
%  		/*
%  		 * All other cases involving NaN return NaN + I*NaN.

Just filter out NaNs (almost) first, and add special cases for Infs
combined with NaNs.

% @@ -299,7 +295,16 @@
%  		 */
%  		/* Bruce Evans tells me this is the way to do this: */
% -		return (cpack((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% +		return (cpack(x+0.0L+(y+0), x+0.0L+(y+0)));

I omitted unnecessary parentheses in the last few versions of it.

%  	}
% 
% +	if (ax > 1/DBL_EPSILON || ay > 1/DBL_EPSILON)
% +		if (ISINF(bx) || ISINF(by) || (int)(1+tiny)==1) { /* raise inexact */
% +			if (SIGNBIT(bx) == 0)
% +				w = clog_for_large_values(z) + M_LN2;
% +			else
% +				w = clog_for_large_values(-z) + M_LN2;
% +			return (cpack(copysign(creal(w), x), copysign(cimag(w), y)));
% +		}
% +
%  	if (ax < DBL_EPSILON && ay < DBL_EPSILON)
%  		if ((int)ax==0 && (int)ay==0) /* raise inexact */

Not actually changed.

% @@ -355,17 +360,11 @@
%  	ay = fabs(y);
% 
% -	if (ax > 1/DBL_EPSILON || ay > 1/DBL_EPSILON)
% -		if (ISINF(bx) || ISINF(by) || (int)(1+tiny)==1) { /* raise inexact */
% -			w = clog_for_large_values(z);
% -			rx = fabs(cimag(w));
% -			ry = creal(w) + M_LN2;
% -			if (sy == 0)
% -				ry = -ry;
% -			return (cpack(rx, ry));
% -		}
% -

Not actually changed.

%  	if (ISNAN(x) || ISNAN(y)) {
%  		/* cacos(0 + I*NaN) = PI/2 + I*NaN */
%  		if (x == 0) return (cpack(M_PI_2, y+y));
% +		/* cacosh(+-Inf + I*NaN) = +Inf + I*NaN */
% +		/* cacosh(NaN + I*+-Inf) = +Inf + I*NaN */
% +		if (ISINF(bx) || ISINF(by))
% +			return (cpack(INFINITY, x+y));
%  		/*
%  		 * All other cases involving NaN return NaN + I*NaN.

cacosh() is simpler because the sign of the infinity is always plus.

The code is suboptimal for both -- once x is nan, it can't be inf,
so the code should probably be written as:

 	if (ISNAN(x)) {
 		// special case for y being inf
 		...
 	}
 	if (ISNAN(y)) {
 		// special case for x being inf
 		...
 	}

% @@ -373,8 +372,17 @@
%  		 * the arguments is not NaN, so we opt not to raise it.
%  		 */
% -		/* Bruce Evans tells me this is the way to do this: */
% -		return (cpack((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% +		return (cpack(x+0.0L+(y+0), x+0.0L+(y+0)));

Don't tell everyone the same thing 3 times.

%  	}
% 
% +	if (ax > 1/DBL_EPSILON || ay > 1/DBL_EPSILON)
% +		if (ISINF(bx) || ISINF(by) || (int)(1+tiny)==1) { /* raise inexact */
% +			w = clog_for_large_values(z);
% +			rx = fabs(cimag(w));
% +			ry = creal(w) + M_LN2;
% +			if (sy == 0)
% +				ry = -ry;
% +			return (cpack(rx, ry));
% +		}
% +
%  	if (ax < DBL_EPSILON && ay < DBL_EPSILON)
%  		if ((int)ax==0 && (int)ay==0) { /* raise inexact */

Not really changed.

% @@ -423,9 +431,4 @@
%  	x = creal(z);
%  	y = cimag(z);
% -
% -	/* Handle NaNs using the general formula to mix them right. */
% -	if (x != x || y != y)
% -		return (cpack(log(hypot(x, y)), atan2(y, x)));
% -
%  	ax = fabs(x);
%  	ay = fabs(y);

Not needed now.

% @@ -558,6 +561,5 @@
%  		 * the arguments is not NaN, so we opt not to raise it.
%  		 */
% -		/* Bruce Evans tells me this is the way to do this: */
% -		return (cpack((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% +		return (cpack(x+0.0L+(y+0), x+0.0L+(y+0)));
%  	}
% 
% diff -u2 catrigf.c~ catrigf.c
% --- catrigf.c~	2012-09-12 02:43:45.000000000 +0000
% +++ catrigf.c	2012-09-12 12:32:19.157537000 +0000
% @@ -25,9 +25,14 @@
%   */
% 
% -#define FOUR_SQRT_MIN		1e-17F
% -#define FOURTH_SQRT_MAX		1e17F
% -
%  static const float
% -tiny = 1e-15;
% +FOUR_SQRT_MIN	= 0x1p-61,
% +FOURTH_SQRT_MAX	= 0x1p61,
% +M_E		= 2.7182818285e0,	/*  0xadf854.0p-22 */
% +M_LN2		= 6.9314718056e-1,	/*  0xb17218.0p-24 */
% +M_PI_2		= 1.5707963268e0,	/*  0xc90fdb.0p-23 */
% +half		= 0.5,
% +quarter		= 0.25;
% +static const volatile
% +tiny		= 0x1p-100;
% 
%  /*

Use normal fdlibm style of consts instead of macros, and fix the type of
most of the constants.

Use hex constants for things related to powers of 2.

Use a more normal value for `tiny'.  fdlibm normally uses (float)1e-30
for the float tiny, so that squaring it underflows to 0, and then sometimes
uses the same variable for setting inexact.  Here we only use it for setting
inexact, and the value of 1e-15 makes no sense for just that.  FLT_EPSILON/2
would make sense for just that (adding it to 1).  But use the tinier `tiny',
in a hex form (the magic -100 is somehwhat less than FLT_MIN_EXP).  In
existing code `tiny' in hex is used mainly in long double code.  2**-100
is used in e_expf.c but is not spelled `tiny' there.

Make `tiny' volatile as usual, to avoid bugs in clang.

% @@ -46,4 +51,7 @@
%  #include <float.h>
%  #include <math.h>
% +#undef M_E
% +#undef M_LN2
% +#undef M_PI_2
%  #include "math_private.h"
%

The constants should all be in lower case, and nothing in <math.h> should
be used in any precision, so that namespace pollution in <math.h> doesn't
matter.

% @@ -56,7 +64,7 @@
%  f(float a, float b, float hypot_a_b)
%  {
% -	if (b < 0) return (0.5 * (hypot_a_b - b));
% -	if (b == 0) return (0.5*a);
% -	return (0.5 * a*a / (hypot_a_b + b));
% +	if (b < 0) return (half * (hypot_a_b - b));
% +	if (b == 0) return (half*a);
% +	return (half * a*a / (hypot_a_b + b));
%  }
%

Global substitution of 0.5 by `half' gives large diffs.

% @@ -71,5 +79,5 @@
% 
% 
% -	A = 0.5*(R + S);
% +	A = half*(R + S);
%  	if (A < 1) A = 1;
% 
% @@ -106,5 +114,5 @@
% 
% 
% -	if (*B > 0.6417) {
% +	if (*B > 0.6417F) {
%  		*B_is_usable = 0;
%  		if (x >= FLT_EPSILON * fabsf(y-1) && x >= FOUR_SQRT_MIN) {

Another double constant.  Putting `half' in the constant table gives the
same spelling for it in all precisions.  This magic number could go there
too, but I don't know a good name for it.

% @@ -113,5 +121,5 @@
%  		} else if (y == 1) {
%  			if ((int)x==0)
% -				*sqrt_A2my2 = sqrtf(x)*sqrtf(0.5*(A+y));
% +				*sqrt_A2my2 = sqrtf(x)*sqrtf(half*(A+y));
%  		} else if (y > 1) {
%  			if ((int)x==0)
% @@ -137,4 +145,14 @@
%  	ay = fabsf(y);
% 
% +	if (isnan(x) || isnan(y)) {
% +
% +		if (y == 0) return (cpackf(x+x, y));
% +		if (isinf(x)) return (cpackf(x, y+y));
% +		if (isinf(y))
% +			return (cpackf(y+y, x));
% +
% +		return (cpackf(x+0.0L+(y+0), x+0.0L+(y+0)));
% +	}
% +
%  	if (ax > 1/FLT_EPSILON || ay > 1/FLT_EPSILON)
%  		if (isinf(x) || isinf(y) || (int)(1+tiny)==1) {
% @@ -146,11 +164,4 @@
%  		}
% 
% -	if (isnan(x) || isnan(y)) {
% -
% -		if (y == 0) return (cpackf(x+x, y));
% -
% -		return (cpackf((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% -	}
% -
%  	if (ax < FLT_EPSILON && ay < FLT_EPSILON)
%  		if ((int)ax==0 && (int)ay==0)
% @@ -187,4 +198,13 @@
%  	ay = fabsf(y);
% 
% +	if (isnan(x) || isnan(y)) {
% +
% +		if (x == 0) return (cpackf(M_PI_2, y+y));
% +		if (isinf(x) || isinf(y))
% +			return (cpackf(INFINITY, x+y));
% +
% +		return (cpackf(x+0.0L+(y+0), x+0.0L+(y+0)));
% +	}
% +
%  	if (ax > 1/FLT_EPSILON || ay > 1/FLT_EPSILON)
%  		if (isinf(x) || isinf(y) || (int)(1+tiny)==1) {
% @@ -197,11 +217,4 @@
%  		}
% 
% -	if (isnan(x) || isnan(y)) {
% -
% -		if (x == 0) return (cpackf(M_PI_2, y+y));
% -
% -		return (cpackf((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% -	}
% -
%  	if (ax < FLT_EPSILON && ay < FLT_EPSILON)
%  		if ((int)ax==0 && (int)ay==0) {
% @@ -242,9 +255,4 @@
%  	x = crealf(z);
%  	y = cimagf(z);
% -
% -
% -	if (x != x || y != y)
% -		return (cpackf(logf(hypotf(x, y)), atan2f(y, x)));
% -
%  	ax = fabsf(x);
%  	ay = fabsf(y);
% @@ -255,5 +263,5 @@
%  	}
% 
% -	if (ax > 0.5*FLT_MAX)
% +	if (ax > half*FLT_MAX)
%  		return (cpackf(logf(hypotf(x / M_E, y / M_E)) + 1, atan2f(y, x)));
% 
% @@ -261,5 +269,5 @@
%  		return (cpackf(logf(hypotf(x, y)), atan2f(y, x)));
% 
% -	return (cpackf(logf(ax*ax + ay*ay) * 0.5, atan2f(y, x)));
% +	return (cpackf(logf(ax*ax + ay*ay) * half, atan2f(y, x)));
%  }
% 
% @@ -317,5 +325,5 @@
%  			return (cpackf(x, y+y));
% 
% -		return (cpackf((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% +		return (cpackf(x+0.0L+(y+0), x+0.0L+(y+0)));
%  	}
% 
% @@ -331,10 +339,10 @@
%  		if ((int)ay==0) {
%  			if ( ilogbf(ay) > FLT_MIN_EXP)
% -				rx = - 0.5 * logf(0.5*ay);
% +				rx = - half * logf(half*ay);
%  			else
% -				rx = - 0.5 * (logf(ay) - M_LN2);
% +				rx = - half * (logf(ay) - M_LN2);
%  		}
%  	} else
% -		rx = 0.25 * log1pf(4*ax / sum_squares(ax-1, ay));
% +		rx = quarter * log1pf(4*ax / sum_squares(ax-1, ay));
% 
%  	if (ax == 1) {
% @@ -342,10 +350,10 @@
%  			ry = 0;
%  		else
% -			ry = 0.5 * atan2f(2, -ay);
% +			ry = half * atan2f(2, -ay);
%  	} else if (ay < FOUR_SQRT_MIN) {
%  		if ((int)ay==0)
% -			ry = 0.5 * atan2f(2*ay, (1-ax)*(1+ax));
% +			ry = half * atan2f(2*ay, (1-ax)*(1+ax));
%  	} else
% -		ry = 0.5 * atan2f(2*ay, (1-ax)*(1+ax) - ay*ay);
% +		ry = half * atan2f(2*ay, (1-ax)*(1+ax) - ay*ay);
% 
%  	return (cpackf(copysignf(rx, x), copysignf(ry, y)));
% diff -u2 catrigl.c~ catrigl.c
% --- catrigl.c~	2012-09-12 02:43:43.000000000 +0000
% +++ catrigl.c	2012-09-12 11:08:34.955652000 +0000
% @@ -141,4 +141,15 @@
%  	ay = fabsl(y);
% 
% +	if (isnan(x) || isnan(y)) {
% +
% +		if (y == 0) return (cpackl(x+x, y));
% +		if (isinf(x))
% +			return (cpackl(x, y+y));
% +		if (isinf(y))
% +			return (cpackl(y+y, x));
% +
% +		return (cpackl(x+0.0L+(y+0), x+0.0L+(y+0)));
% +	}
% +
%  	if (ax > 1/LDBL_EPSILON || ay > 1/LDBL_EPSILON)
%  		if (isinf(x) || isinf(y) || (int)(1+tiny)==1) {
% @@ -150,11 +161,4 @@
%  		}
% 
% -	if (isnan(x) || isnan(y)) {
% -
% -		if (y == 0) return (cpackl(x+x, y));
% -
% -		return (cpackl((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% -	}
% -
%  	if (ax < LDBL_EPSILON && ay < LDBL_EPSILON)
%  		if ((int)ax==0 && (int)ay==0)
% @@ -191,4 +195,13 @@
%  	ay = fabsl(y);
% 
% +	if (isnan(x) || isnan(y)) {
% +
% +		if (x == 0) return (cpackl(L_PI_2, y+y));
% +		if (isinf(x) || isinf(y))
% +			return (cpackl(INFINITY, x+y));
% +
% +		return (cpackl(x+0.0L+(y+0), x+0.0L+(y+0)));
% +	}
% +
%  	if (ax > 1/LDBL_EPSILON || ay > 1/LDBL_EPSILON)
%  		if (isinf(x) || isinf(y) || (int)(1+tiny)==1) {
% @@ -201,11 +214,4 @@
%  		}
% 
% -	if (isnan(x) || isnan(y)) {
% -
% -		if (x == 0) return (cpackl(L_PI_2, y+y));
% -
% -		return (cpackl((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% -	}
% -
%  	if (ax < LDBL_EPSILON && ay < LDBL_EPSILON)
%  		if ((int)ax==0 && (int)ay==0) {
% @@ -246,9 +252,4 @@
%  	x = creall(z);
%  	y = cimagl(z);
% -
% -
% -	if (x != x || y != y)
% -		return (cpackl(logl(hypotl(x, y)), atan2l(y, x)));
% -
%  	ax = fabsl(x);
%  	ay = fabsl(y);
% @@ -321,5 +322,5 @@
%  			return (cpackl(x, y+y));
% 
% -		return (cpackl((x+0.0L)+(y+0), (x+0.0L)+(y+0)));
% +		return (cpackl(x+0.0L+(y+0), x+0.0L+(y+0)));
%  	}
%

The errors have now changed only slightly.  This is only for i386:

Float precision:

% 1,6c1,6
% old< rcacos:max_er = 0x4517ee94 2.1592, avg_er = 0.314, #>=1:0.5 = 3786:214820
% old< rcacosh:max_er = 0x3170e232 1.5450, avg_er = 0.253, #>=1:0.5 = 1196:3225128
% old< rcasin:max_er = 0x55adc0df 2.6775, avg_er = 0.208, #>=1:0.5 = 34228:360900
% old< rcasinh:max_er = 0x3170e232 1.5450, avg_er = 0.253, #>=1:0.5 = 1196:3225128
% old< rcatan:max_er = 0x3c4078ec 1.8829, avg_er = 0.284, #>=1:0.5 = 13260:190836
% old< rcatanh:max_er = 0x2cef3171 1.4042, avg_er = 0.167, #>=1:0.5 = 4096:420916
% ---
% new> rcacos:max_er = 0x4517ee94 2.1592, avg_er = 0.315, #>=1:0.5 = 4608:247032
% new> rcacosh:max_er = 0x3170e232 1.5450, avg_er = 0.250, #>=1:0.5 = 1392:3151892
% new> rcasin:max_er = 0x55adc0df 2.6775, avg_er = 0.208, #>=1:0.5 = 35072:362768
% new> rcasinh:max_er = 0x3170e232 1.5450, avg_er = 0.250, #>=1:0.5 = 1392:3151892
% new> rcatan:max_er = 0x3c4078ec 1.8829, avg_er = 0.287, #>=1:0.5 = 37132:302960
% new> rcatanh:max_er = 0x2cef3171 1.4042, avg_er = 0.166, #>=1:0.5 = 4096:357284

The number of incorrectly rounded cases went up most for catan.

Fixing the constants actually reduced the errors slightly -- the ones that
are now 1392:* (up from 1196:*) were over 30000:* in an intermediate version.

% 16,21c16,21
% old< icacos:max_er = 0x3170e232 1.5450, avg_er = 0.253, #new>=1:0.5 = 1196:3225128
% old< icacosh:max_er = 0x4517ee94 2.1592, avg_er = 0.314, #new>=1:0.5 = 3786:214820
% old< icasin:max_er = 0x3170e232 1.5450, avg_er = 0.253, #new>=1:0.5 = 1196:3225128
% old< icasinh:max_er = 0x55adc0df 2.6775, avg_er = 0.208, #new>=1:0.5 = 34228:360900
% old< icatan:max_er = 0x2cef3171 1.4042, avg_er = 0.167, #new>=1:0.5 = 4096:420916
% old< icatanh:max_er = 0x3c4078ec 1.8829, avg_er = 0.284, #new>=1:0.5 = 13260:190836
% ---
% new> icacos:max_er = 0x3170e232 1.5450, avg_er = 0.250, #>=1:0.5 = 1392:3151892
% new> icacosh:max_er = 0x4517ee94 2.1592, avg_er = 0.315, #>=1:0.5 = 4608:247032
% new> icasin:max_er = 0x3170e232 1.5450, avg_er = 0.250, #>=1:0.5 = 1392:3151892
% new> icasinh:max_er = 0x55adc0df 2.6775, avg_er = 0.208, #>=1:0.5 = 35072:362768
% new> icatan:max_er = 0x2cef3171 1.4042, avg_er = 0.166, #>=1:0.5 = 4096:357284
% new> icatanh:max_er = 0x3c4078ec 1.8829, avg_er = 0.287, #>=1:0.5 = 37132:302960
% 
% Double precision:
% 31,36c31,36
% old< rcacos:max_er =     0x1b5a 3.4189, avg_er = 0.166, #new>=1:0.5 = 2394:118150
% old< rcacosh:max_er =      0xf8a 1.9424, avg_er = 0.258, #new>=1:0.5 = 8444:2737804
% old< rcasin:max_er =     0x15c5 2.7212, avg_er = 0.113, #new>=1:0.5 = 33308:99188
% old< rcasinh:max_er =      0xf8a 1.9424, avg_er = 0.258, #new>=1:0.5 = 8444:2737804
% old< rcatan:max_er =     0x1622 2.7666, avg_er = 0.016, #new>=1:0.5 = 4680:81364
% old< rcatanh:max_er =     0x14b9 2.5903, avg_er = 0.047, #new>=1:0.5 = 428996:691360
% ---
% new> rcacos:max_er =     0x1b5a 3.4189, avg_er = 0.168, #>=1:0.5 = 2414:110360
% new> rcacosh:max_er =      0xf8a 1.9424, avg_er = 0.257, #>=1:0.5 = 24192:2683944
% new> rcasin:max_er =     0x15c5 2.7212, avg_er = 0.113, #>=1:0.5 = 33864:100284
% new> rcasinh:max_er =      0xf8a 1.9424, avg_er = 0.257, #>=1:0.5 = 24192:2683944
% new> rcatan:max_er =     0x1622 2.7666, avg_er = 0.015, #>=1:0.5 = 20580:101564
% new> rcatanh:max_er =     0x14b9 2.5903, avg_er = 0.044, #>=1:0.5 = 403028:652792
% 39,44c39,44
% old< icacos:max_er =      0xf8a 1.9424, avg_er = 0.258, #new>=1:0.5 = 8444:2737804
% old< icacosh:max_er =     0x1b5a 3.4189, avg_er = 0.166, #new>=1:0.5 = 2394:118150
% old< icasin:max_er =      0xf8a 1.9424, avg_er = 0.258, #new>=1:0.5 = 8444:2737804
% old< icasinh:max_er =     0x15c5 2.7212, avg_er = 0.113, #new>=1:0.5 = 33308:99188
% old< icatan:max_er =     0x14b9 2.5903, avg_er = 0.047, #new>=1:0.5 = 428996:691360
% old< icatanh:max_er =     0x1622 2.7666, avg_er = 0.016, #new>=1:0.5 = 4680:81364
% ---
% new> icacos:max_er =      0xf8a 1.9424, avg_er = 0.257, #>=1:0.5 = 24192:2683944
% new> icacosh:max_er =     0x1b5a 3.4189, avg_er = 0.168, #>=1:0.5 = 2414:110360
% new> icasin:max_er =      0xf8a 1.9424, avg_er = 0.257, #>=1:0.5 = 24192:2683944
% new> icasinh:max_er =     0x15c5 2.7212, avg_er = 0.113, #>=1:0.5 = 33864:100284
% new> icatan:max_er =     0x14b9 2.5903, avg_er = 0.044, #>=1:0.5 = 403028:652792
% new> icatanh:max_er =     0x1622 2.7666, avg_er = 0.015, #>=1:0.5 = 20580:101564

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120912225847.J1771>