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