[Cfp-interest 1851] Re: Negative zero

Mike Cowlishaw mfc at speleotrove.com
Sat Nov 21 12:23:16 PST 2020


The signbit macro returns a nonzero value if and only if the sign of its
argument value is negative. 

That indeed does not sound 'right'.   I just did a quick check of where I
use signbit(); code attached below -- it assumes it is the sign bit in the
encoding that is being tested, I think, not 'negativity'.
 
(Caveat: this code is some years old and might well have errors, and might
not reflect recent 754 changes.   It is/was my best attempt at creating an
atan2 (degrees, approximated) that was fast enough to be usable as the
'obvious' atan2d (also below) was too slow.)
 
Mike
 
------------------------------------
 
/* --------------------------------------------------------------- */
/* atan2d -- arc tangent of y/x in degrees                         */
/*                                                                 */
/*   y -- Y-coordinate [-inf -> +inf]                              */
/*   x -- X-coordinate [-inf -> +inf]                              */
/*                                                                 */
/*   returns the principal value of the arc tangent of y/x, in     */
/*   degrees from -180 through +180                                */
/*                                                                 */
/* The signs of the arguments are used to determine the quadrant,  */
/* and hence the sign and value, of the result.  If x and y are    */
/* both 0 then 0 is returned.                                      */
/*                                                                 */
/* No argument error is possible.                                  */
/*                                                                 */
/* For example:                                                    */
/*                                                                 */
/*   atan2d( 10,  10) => 45                                        */
/*   atan2d(-10,  10) => -45                                       */
/*   atan2d( 10, -10) => 135                                       */
/*   atan2d(-10, -10) => -135                                      */
/*   atan2d(  0,   0) => 0                                         */
/*   atan2d(  0,  -0) => 180                                       */
/*   atan2d( -0,   0) => -0                                        */
/*   atan2d( -0,  -0) => -180                                      */
/*                                                                 */
/* (see the IEEE 754 standard for other special cases).            */
/* --------------------------------------------------------------- */
degree atan2d(double y, double x) {
  return Rad2Deg(atan2(y, x));          // use library function
  } // atan2d
 
/* --------------------------------------------------------------- */
/* atan2da -- arc tangent of y/x in degrees approximation          */
/*                                                                 */
/*   y -- Y-coordinate [-inf -> +inf]                              */
/*   x -- X-coordinate [-inf -> +inf]                              */
/*                                                                 */
/*   returns the principal value of the arc tangent of y/x, in     */
/*   degrees from -180 through +180                                */
/*                                                                 */
/* See atan2d for description of the function.                     */
/*                                                                 */
/* This approximation is from Rajan et al, 2006, wrapped in atan2  */
/* wrapper due to 'imuli' 2017.                                    */
/*                                                                 */
/* Special cases for infinite x or y not included.                 */
/*                                                                 */
/* 4.1x faster than base; max error 0.086°                         */
/* --------------------------------------------------------------- */
degree atan2da(double y, double x) {
 
  if (y==0.0) {                              // y is a 0 (sign matters)
    if (signbit(y)) {
      if (signbit(x)) return -180;
      return NEG0;
      }
    // y is +0
    if (signbit(x)) return 180;
    return +0;
    }
  if (x==0) {                                // x is 0
    if (y<0) return -90;
    return 90;
    }
  // here both x and y are non-zero
 
  double absy=fabs(y);
  double absx=fabs(x);
 
  Flag invert=absy>absx;
  double z=invert ? absx/absy : absy/absx;   // [0..1]
  // z is >=0
 
  // atan_approx [-1<=z<=1] ...
  double th=(MAT_PI/4)*z - z*(z-1)*(0.2447 + 0.0663*z);        // Eq 9
 
  // Eq. 7 is slower(!) and less accurate (0.21°) than Eq. 9:
  // double th=(MAT_PI/4)*z + 0.273*z*(1.0-z);                 // Eq 7
 
  if (invert) th=(MAT_PI/2)-th;
  if (signbit(x)) th=MAT_PI-th;
  if (signbit(y)) return Rad2Deg(-th);
  return Rad2Deg(th);
  } // atan2da

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.oakapple.net/pipermail/cfp-interest/attachments/20201121/0cf7ae41/attachment-0001.htm>


More information about the Cfp-interest mailing list