this repo has no description
at fixPythonPipStalling 315 lines 13 kB view raw
1/* This is an implementation of tanf. It is written in standard C except that 2 float must have an IEEE 754 single-precision implementation, and its 3 exponent field is accessed via a union and a struct containing bit fields. 4 It should be good enough to serve as the libm tanf with tolerable 5 performance. (The exponent field access could be replaced with ilogbf to 6 make this a standard C routine, but additional branches would be required 7 and performance would be impaired.) 8 9 When this file is compiled, a definition must be supplied for the 10 preprocessor symbol Name. This both becomes the name of the routine and 11 specifies the function to perform. The only supported name is: 12 13 tanf Tangent function. 14*/ 15 16 17// Define constants for preprocessor conditionals. 18#define Tangent 1 19 20// Temporarily define symbols so we can use preprocessor tests. 21#define tanf Tangent 22 23#if Name == Tangent 24 #define Function Tangent 25#else 26 #error "Unknown function." 27#endif 28 29// Remove temporary definitions. 30#undef tanf 31 32#define ExponentFold 1 33 34 35// Include math.h to ensure we match the declarations of tanf. 36#include <math.h> 37 38 39// Describe the destination floating-point type. 40#define SignificandBits 24 41#define ExponentBits 8 42 43 44/* float Name(float x). 45 46 Notes: 47 48 Citations in parentheses below indicate the source of a requirement. 49 50 "C" stands for ISO/IEC 9899:TC2. 51 52 The Open Group specification (IEEE Std 1003.1, 2004 edition) adds no 53 requirements since it defers to C and requires errno behavior only if 54 we choose to support it by arranging for "math_errhandling & 55 MATH_ERRNO" to be non-zero, which we do not. 56 57 Return value: 58 59 For tangent of +/- zero, return zero with same sign (C F.9 12 and 60 F.9.1.7). 61 62 For +/- infinity, return NaN (C F.9.1.7). 63 64 For a NaN, return the same NaN (C F.9 11 and 13). 65 66 Otherwise: 67 68 If the rounding mode is round-to-nearest, return tangent(x) 69 faithfully rounded. 70 71 Not implemented: In other rounding modes, return tangent(x) 72 possibly with slightly worse error, not necessarily honoring the 73 rounding mode (Ali Sazegari narrowing C F.9 10). 74 75 Exceptions: 76 77 Raise underflow for a denormal result (C F.9 7 and Draft Standard for 78 Floating-Point Arithmetic P754 Draft 1.2.5 9.5). If the input is the 79 smallest normal, underflow may or may not be raised. This is stricter 80 than the older 754 standard. 81 82 May or may not raise inexact, even if the result is exact (C F.9 8). 83 84 Raise invalid if the input is a signalling NaN (C 5.2.4.2.2 3, in spite 85 of C 4.2.1) or an infinity (C F.9.1.7) but not if the input is a quiet 86 NaN (C F.9 11). 87 88 May not raise exceptions otherwise (C F.9 9). 89 90 Properties: 91 92 Monotonic. Not yet proven. 93*/ 94float Name(float x) 95{ 96 if (isnan(x)) 97 return x; 98 99 #if defined __STDC__ && 199901L <= __STDC_VERSION__ && !defined __GNUC__ 100 // GCC does not currently support FP_CONTRACT. Maybe someday. 101 #pragma STDC FP_CONTRACT OFF 102 #endif 103 104 typedef struct { double m0, m1; } Double2; 105 106 /* This table was generated by tanfMakeTable.c. */ 107 108 static const Double2 ReductionTable[] = 109 { 110 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -126. 111 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -125. 112 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -123. 113 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -121. 114 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -119. 115 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -117. 116 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -115. 117 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -113. 118 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -111. 119 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -109. 120 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -107. 121 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -105. 122 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -103. 123 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -101. 124 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -99. 125 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -97. 126 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -95. 127 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -93. 128 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -91. 129 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -89. 130 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -87. 131 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -85. 132 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -83. 133 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -81. 134 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -79. 135 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -77. 136 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -75. 137 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -73. 138 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -71. 139 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -69. 140 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -67. 141 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -65. 142 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -63. 143 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -61. 144 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -59. 145 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -57. 146 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -55. 147 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -53. 148 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -51. 149 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -49. 150 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -47. 151 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -45. 152 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -43. 153 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -41. 154 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -39. 155 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -37. 156 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -35. 157 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -33. 158 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -31. 159 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -29. 160 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -27. 161 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -25. 162 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -23. 163 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -21. 164 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -19. 165 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -17. 166 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -15. 167 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -13. 168 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -11. 169 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -9. 170 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -7. 171 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -5. 172 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -3. 173 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent -1. 174 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 1. 175 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 3. 176 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 5. 177 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 7. 178 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 9. 179 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 11. 180 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 13. 181 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 15. 182 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 17. 183 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 19. 184 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 21. 185 { 0x1.45f306ep-1, -0x1.b1bbead603d8bp-32 }, // Exponent 23. 186 { 0x1.17cc1b7p-3, 0x1.391054a7f09d6p-34 }, // Exponent 25. 187 { 0x1.7cc1b72p-7, 0x1.c882a53f84ebp-37 }, // Exponent 27. 188 { 0x1.7cc1b72p-7, 0x1.c882a53f84ebp-37 }, // Exponent 29. 189 { 0x1.f306dcap-9, -0x1.bbead603d8a83p-40 }, // Exponent 31. 190 { -0x1.9f246c7p-14, 0x1.054a7f09d5f48p-46 }, // Exponent 33. 191 { -0x1.9f246c7p-14, 0x1.054a7f09d5f48p-46 }, // Exponent 35. 192 { 0x1.836e4e4p-16, 0x1.054a7f09d5f48p-46 }, // Exponent 37. 193 { -0x1.f246c6fp-18, 0x1.529fc2757d1f5p-52 }, // Exponent 39. 194 { 0x1.b727221p-23, -0x1.5ac07b1505c16p-53 }, // Exponent 41. 195 { 0x1.b727221p-23, -0x1.5ac07b1505c16p-53 }, // Exponent 43. 196 { 0x1.b727221p-23, -0x1.5ac07b1505c16p-53 }, // Exponent 45. 197 { -0x1.236377dp-25, -0x1.6b01ec5417056p-55 }, // Exponent 47. 198 { -0x1.1b1bbebp-28, 0x1.4fe13abe8fa9ap-59 }, // Exponent 49. 199 { 0x1.c9c882ap-29, 0x1.4fe13abe8fa9ap-59 }, // Exponent 51. 200 { -0x1.b1bbeadp-32, -0x1.80f62a0b82b2dp-62 }, // Exponent 53. 201 { 0x1.391054ap-34, 0x1.fc2757d1f534ep-64 }, // Exponent 55. 202 { -0x1.8ddf56bp-35, -0x1.ec54170565912p-71 }, // Exponent 57. 203 { 0x1.c882a54p-37, -0x1.ec54170565912p-71 }, // Exponent 59. 204 { -0x1.bbead6p-40, -0x1.ec54170565912p-71 }, // Exponent 61. 205 { 0x1.1054a7fp-42, 0x1.3abe8fa9a6eep-75 }, // Exponent 63. 206 { -0x1.df56b02p-43, 0x1.3abe8fa9a6eep-75 }, // Exponent 65. 207 { 0x1.054a7f1p-46, -0x1.8a82e0acb223fp-76 }, // Exponent 67. 208 { -0x1.f56b01fp-47, 0x1.d5f47d4d37703p-78 }, // Exponent 69. 209 { 0x1.529fc27p-52, 0x1.5f47d4d377037p-82 }, // Exponent 71. 210 { 0x1.529fc27p-52, 0x1.5f47d4d377037p-82 }, // Exponent 73. 211 { -0x1.5ac07b1p-53, -0x1.4170565911f92p-83 }, // Exponent 75. 212 { -0x1.6b01ec5p-55, -0x1.05c1596447e49p-85 }, // Exponent 77. 213 { -0x1.ac07b15p-57, -0x1.70565911f924fp-91 }, // Exponent 79. 214 { 0x1.4fe13acp-59, -0x1.70565911f924fp-91 }, // Exponent 81. 215 { 0x1.3f84ebp-61, -0x1.70565911f924fp-91 }, // Exponent 83. 216 { 0x1.fc2757dp-64, 0x1.f534ddc0db629p-96 }, // Exponent 85. 217 { -0x1.ec5417p-71, -0x1.596447e493ad5p-101 }, // Exponent 87. 218 { -0x1.ec5417p-71, -0x1.596447e493ad5p-101 }, // Exponent 89. 219 { -0x1.ec5417p-71, -0x1.596447e493ad5p-101 }, // Exponent 91. 220 { -0x1.ec5417p-71, -0x1.596447e493ad5p-101 }, // Exponent 93. 221 { 0x1.3abe8fbp-75, -0x1.96447e493ad4dp-105 }, // Exponent 95. 222 { 0x1.3abe8fbp-75, -0x1.96447e493ad4dp-105 }, // Exponent 97. 223 { 0x1.d5f47d5p-78, -0x1.6447e493ad4cep-109 }, // Exponent 99. 224 { -0x1.505c159p-81, -0x1.911f924eb5336p-111 }, // Exponent 101. 225 { -0x1.505c159p-81, -0x1.911f924eb5336p-111 }, // Exponent 103. 226 { -0x1.4170566p-83, 0x1.bb81b6c52b328p-113 }, // Exponent 105. 227 { -0x1.05c1596p-85, -0x1.11f924eb53362p-115 }, // Exponent 107. 228 { -0x1.7056591p-91, -0x1.f924eb53361dep-123 }, // Exponent 109. 229 { -0x1.7056591p-91, -0x1.f924eb53361dep-123 }, // Exponent 111. 230 { -0x1.7056591p-91, -0x1.f924eb53361dep-123 }, // Exponent 113. 231 { -0x1.c159644p-93, -0x1.f924eb53361dep-123 }, // Exponent 115. 232 { 0x1.f534ddcp-96, 0x1.b6c52b3278872p-129 }, // Exponent 117. 233 { -0x1.596447ep-101, -0x1.24eb53361de38p-131 }, // Exponent 119. 234 { -0x1.596447ep-101, -0x1.24eb53361de38p-131 }, // Exponent 121. 235 { -0x1.596447ep-101, -0x1.24eb53361de38p-131 }, // Exponent 123. 236 { -0x1.65911f9p-103, -0x1.275a99b0ef1bfp-134 }, // Exponent 125. 237 { -0x1.96447e5p-105, 0x1.b14acc9e21c82p-135 }, // Exponent 127. 238 }; 239 240 // Define a structure for accessing the internal components of a float. 241 typedef union 242 { 243 float f; 244 struct 245 { 246 #if defined __BIG_ENDIAN__ 247 unsigned int sign : 1; 248 unsigned int exponent : ExponentBits; 249 unsigned int fraction : SignificandBits-1; 250 #else // defined __BIG_ENDIAN__ 251 unsigned int fraction : SignificandBits-1; 252 unsigned int exponent : ExponentBits; 253 unsigned int sign : 1; 254 #endif // defined __BIG_ENDIAN__ 255 } s; 256 } Float; 257 258 Float X = { x }; 259 260 /* Look up 2**ArcBits * (u/p % 1)/u in the reduction table. See 261 tanfMakeTable.c for more information. The properties we need are: 262 263 The multiplication of residue.m0 by x is exact. 264 265 Let ki be residue.m0 * x rounded to an integer. 266 267 Let xr be residue.m0 * x - ki + residue.m1 * x. 268 269 If ki is even, the tangent of xr is nearly equal to the tangent of 270 x. 271 272 If ki is odd, the negative of the tangent of xr is nearly equal to 273 the tangent of x. 274 */ 275 Double2 residue = ReductionTable[X.s.exponent >> ExponentFold]; 276 277 double p = x * residue.m0; 278 279 // Round p to an integer in k. 280 int ki = (int) lrint(p); 281 double k = ki; 282 /* Alternatives to lrint: 283 284 Use nearbyint. This will not raise the inexact exception. 285 However, we already raise inexact in the version-two polynomial 286 even when x is zero. 287 288 Use lround. This will take longer but will round to nearest 289 regardless of rounding mode. 290 */ 291 292 double f0 = p - k; 293 double f1 = x * residue.m1; 294 295 // xr is x reduced to a final residue. 296 double xr = f0 + f1; 297 298 // Approximate tangent with a polynomial. 299 300 double x2 = xr*xr; // Square xr. 301 302 double t = 303 ( ((x2 - 0.34431297545117363561) * x2 + 0.75337415977492632831) 304 * ((x2 + 0.91301179133375347365) * x2 + 0.58807104225499649417) 305 ) 306 * 307 ( ((x2 - 1.53503935362160698123) * x2 + 0.92783629599735333058) 308 * (( + 5.27860261872543679865) * x2 + 3.82127246397188494330) 309 ) 310 * 311 xr; 312 313 // If low bit of ki is 1, return t or -1/t according to low bit of ki. 314 return (float) (ki & 1 ? -1/t : t); 315}