atanf.c raw

   1  /* origin: FreeBSD /usr/src/lib/msun/src/s_atanf.c */
   2  /*
   3   * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
   4   */
   5  /*
   6   * ====================================================
   7   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
   8   *
   9   * Developed at SunPro, a Sun Microsystems, Inc. business.
  10   * Permission to use, copy, modify, and distribute this
  11   * software is freely granted, provided that this notice
  12   * is preserved.
  13   * ====================================================
  14   */
  15  
  16  
  17  #include "libm.h"
  18  
  19  static const float atanhi[] = {
  20    4.6364760399e-01, /* atan(0.5)hi 0x3eed6338 */
  21    7.8539812565e-01, /* atan(1.0)hi 0x3f490fda */
  22    9.8279368877e-01, /* atan(1.5)hi 0x3f7b985e */
  23    1.5707962513e+00, /* atan(inf)hi 0x3fc90fda */
  24  };
  25  
  26  static const float atanlo[] = {
  27    5.0121582440e-09, /* atan(0.5)lo 0x31ac3769 */
  28    3.7748947079e-08, /* atan(1.0)lo 0x33222168 */
  29    3.4473217170e-08, /* atan(1.5)lo 0x33140fb4 */
  30    7.5497894159e-08, /* atan(inf)lo 0x33a22168 */
  31  };
  32  
  33  static const float aT[] = {
  34    3.3333328366e-01,
  35   -1.9999158382e-01,
  36    1.4253635705e-01,
  37   -1.0648017377e-01,
  38    6.1687607318e-02,
  39  };
  40  
  41  float atanf(float x)
  42  {
  43  	float_t w,s1,s2,z;
  44  	uint32_t ix,sign;
  45  	int id;
  46  
  47  	GET_FLOAT_WORD(ix, x);
  48  	sign = ix>>31;
  49  	ix &= 0x7fffffff;
  50  	if (ix >= 0x4c800000) {  /* if |x| >= 2**26 */
  51  		if (isnan(x))
  52  			return x;
  53  		z = atanhi[3] + 0x1p-120f;
  54  		return sign ? -z : z;
  55  	}
  56  	if (ix < 0x3ee00000) {   /* |x| < 0.4375 */
  57  		if (ix < 0x39800000) {  /* |x| < 2**-12 */
  58  			if (ix < 0x00800000)
  59  				/* raise underflow for subnormal x */
  60  				FORCE_EVAL(x*x);
  61  			return x;
  62  		}
  63  		id = -1;
  64  	} else {
  65  		x = fabsf(x);
  66  		if (ix < 0x3f980000) {  /* |x| < 1.1875 */
  67  			if (ix < 0x3f300000) {  /*  7/16 <= |x| < 11/16 */
  68  				id = 0;
  69  				x = (2.0f*x - 1.0f)/(2.0f + x);
  70  			} else {                /* 11/16 <= |x| < 19/16 */
  71  				id = 1;
  72  				x = (x - 1.0f)/(x + 1.0f);
  73  			}
  74  		} else {
  75  			if (ix < 0x401c0000) {  /* |x| < 2.4375 */
  76  				id = 2;
  77  				x = (x - 1.5f)/(1.0f + 1.5f*x);
  78  			} else {                /* 2.4375 <= |x| < 2**26 */
  79  				id = 3;
  80  				x = -1.0f/x;
  81  			}
  82  		}
  83  	}
  84  	/* end of argument reduction */
  85  	z = x*x;
  86  	w = z*z;
  87  	/* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
  88  	s1 = z*(aT[0]+w*(aT[2]+w*aT[4]));
  89  	s2 = w*(aT[1]+w*aT[3]);
  90  	if (id < 0)
  91  		return x - x*(s1+s2);
  92  	z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
  93  	return sign ? -z : z;
  94  }
  95