/ src / ref / atanf.c
atanf.c
  1  /*
  2   * Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved.
  3   *
  4   * Redistribution and use in source and binary forms, with or without modification,
  5   * are permitted provided that the following conditions are met:
  6   * 1. Redistributions of source code must retain the above copyright notice,
  7   *    this list of conditions and the following disclaimer.
  8   * 2. Redistributions in binary form must reproduce the above copyright notice,
  9   *    this list of conditions and the following disclaimer in the documentation
 10   *    and/or other materials provided with the distribution.
 11   * 3. Neither the name of the copyright holder nor the names of its contributors
 12   *    may be used to endorse or promote products derived from this software without
 13   *    specific prior written permission.
 14   *
 15   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 16   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 17   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 18   * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 19   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 20   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 21   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 22   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 24   * POSSIBILITY OF SUCH DAMAGE.
 25   *
 26   */
 27  
 28  #include "libm_amd.h"
 29  #include "libm_util_amd.h"
 30  #include "libm_special.h"
 31  
 32  
 33  float FN_PROTOTYPE_REF(atanf)(float fx)
 34  {
 35  
 36    /* Some constants and split constants. */
 37  
 38    static double piby2 = 1.5707963267948966e+00; /* 0x3ff921fb54442d18 */
 39  
 40    double c, v, s, q, z;
 41    unsigned int xnan,fux,faux;
 42    unsigned long long ux, aux, xneg;
 43    double x;
 44     GET_BITS_SP32(fx, fux);
 45     faux = fux & ~SIGNBIT_SP32;
 46  
 47      xnan = (faux > PINFBITPATT_SP32);
 48  
 49        if (xnan)
 50          {
 51            /* x is NaN */
 52  #ifdef WINDOWS
 53  		return  __amd_handle_errorf("atanf", __amd_atan, fux|0x00400000, _DOMAIN,0, EDOM, fx, 0.0, 1);
 54  #else
 55            return fx + fx; /* Raise invalid if it's a signalling NaN */
 56  #endif
 57          }
 58  
 59  
 60  
 61  	  x = fx;
 62      GET_BITS_DP64(x, ux);
 63    /* Find properties of argument fx. */
 64  
 65  
 66    aux = ux & ~SIGNBIT_DP64;
 67    xneg = ux & SIGNBIT_DP64;
 68  
 69    v = x;
 70    if (xneg) v = -x;
 71  
 72    /* Argument reduction to range [-7/16,7/16] */
 73  
 74    if (aux < 0x3ec0000000000000) /* v < 2.0^(-19) */
 75      {
 76        /* x is a good approximation to atan(x) */
 77        if (aux == 0x0000000000000000)
 78          return fx;
 79        else
 80  #ifdef WINDOWS
 81          return fx ; //valf_with_flags(fx, AMD_F_INEXACT);
 82  #else
 83  	return  __amd_handle_errorf("atanf", __amd_atan, fux, _UNDERFLOW, AMD_F_UNDERFLOW|AMD_F_INEXACT, ERANGE, fx, 0.0, 1);
 84  
 85  #endif
 86      }
 87    else if (aux < 0x3fdc000000000000) /* v < 7./16. */
 88      {
 89        x = v;
 90        c = 0.0;
 91      }
 92    else if (aux < 0x3fe6000000000000) /* v < 11./16. */
 93      {
 94        x = (2.0*v-1.0)/(2.0+v);
 95        /* c = arctan(0.5) */
 96        c = 4.63647609000806093515e-01; /* 0x3fddac670561bb4f */
 97      }
 98    else if (aux < 0x3ff3000000000000) /* v < 19./16. */
 99      {
100        x = (v-1.0)/(1.0+v);
101        /* c = arctan(1.) */
102        c = 7.85398163397448278999e-01; /* 0x3fe921fb54442d18 */
103      }
104    else if (aux < 0x4003800000000000) /* v < 39./16. */
105      {
106        x = (v-1.5)/(1.0+1.5*v);
107        /* c = arctan(1.5) */
108        c = 9.82793723247329054082e-01; /* 0x3fef730bd281f69b */
109      }
110    else
111      {
112      if (aux > 0x4190000000000000)
113  	{ /* abs(x) > 2^26 => arctan(1/x) is
114  	     insignificant compared to piby2 */
115  	  if (xneg)
116              return (float)-piby2 ; //valf_with_flags((float)-piby2, AMD_F_INEXACT);
117  	  else
118              return (float)piby2;//valf_with_flags((float)piby2, AMD_F_INEXACT);
119  	}
120  
121        x = -1.0/v;
122        /* c = arctan(infinity) */
123        c = 1.57079632679489655800e+00; /* 0x3ff921fb54442d18 */
124      }
125  
126    /* Core approximation: Remez(2,2) on [-7/16,7/16] */
127  
128    s = x*x;
129    q = x*s*
130      (0.296528598819239217902158651186e0 +
131       (0.192324546402108583211697690500e0 +
132         0.470677934286149214138357545549e-2*s)*s)/
133      (0.889585796862432286486651434570e0 +
134       (0.111072499995399550138837673349e1 +
135         0.299309699959659728404442796915e0*s)*s);
136  
137    z = c - (q - x);
138  
139    if (xneg) z = -z;
140    return (float)z;
141  }
142  
143