this repo has no description
at fixPythonPipStalling 1183 lines 52 kB view raw
1/* 2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22// 23// ArcTanDD.c 24// 25// Double-double Function Library 26// Copyright: � 1995-96 by Apple Computer, Inc., all rights reserved 27// 28// long double atanl( long double x ); 29// long double atan2l( long double y, long double x ); 30// 31// Change History: 32// 8/31/96 - PAF - Changed if() to else (see Note 1) 33// 34 35#include "math.h" 36#include "fp_private.h" 37#if (__WANT_LONG_DOUBLE_FORMAT__ - 0L == 128L) 38#include "DD.h" 39 40static const double kBig = 6.755399441055744e+15; // 0x1.8p52 41 42static const double kPiBy2 = 1.570796326794896619231322; // 0x1.921FB54442D18p0 43static const double kPiBy2Tail1 = 6.123233995736766036e-17; // 0x1.1A62633145C07p-54 44static const double kPiBy2Tail1m = 6.123233995736764803e-17; // 0x1.1A62633145C06p-54 45static const double kPiBy2Tail2 = -1.4973849048591698e-33; // 0x1.F1976B7ED8FBCp-110 46static const double kRecip = 6.869637070016756334588131e-12; // 0x1.e368613a3b430p-38 47static const double kLimit1 = 0.0859375; // 0x1.6p-4 48static const double kLimit2 = 1.015625; 49static const double kLimit3 = 13.0; 50static const double kLimit4 = 8.11296384146066817e+31; // 0x1.0p+106 51static const Float kInfinityu = {0x7f800000}; 52 53//*************************************************************************** 54// factor -> gives the number of table values between the consecutive * 55// integers 1 to 12 * 56//*************************************************************************** 57 58static const float factor[12] = { 59 32.0f,16.0f,8.0f,4.0f,4.0f,2.0f,2.0f,1.0f,1.0f,1.0f,1.0f,1.0f 60}; 61 62 63//*************************************************************************** 64// Adjust -> index into accurate atan table, for integer arguments * 65// from 1 to 12. * 66//*************************************************************************** 67 68static const float adjust[12] = { 69 32.0f,64.0f,88.0f,104.0f,104.0f,116.0f,116.0f,124.0f,124.0f,124.0f,124.0f,124.0f 70}; 71 72 73//*************************************************************************** 74// atancoeff: coefficients of atan approximating polynomial, * 75// multiplied by 145568097675.0 * 76//*************************************************************************** 77 78static const double atancoeff[15] = { 79 145568097675.0, -48522699225.0, 80 29113619535.0, -20795442525.0, 16174233075.0, 81 -13233463425.0, 11197545975.0, -9704539845.0, 82 8562829275.0, -7661478825.0, 6931814175.0, 83 -6329047725.0, 5822723907.0, -5391411025.0, 84 5019589575.0 85}; 86 87static const uint32_t atanTable[] __attribute__ ((aligned(8))) = { 88 89 //******************************************************************* 90 // Accurate table over range ( .093750, .984375). * 91 //******************************************************************* 92 93 0x3FB80000, 0x96AC4A5A, 0x3FB7EE18, 0xBB5F2BDC, 0x3B1F7151, 0xA60EEDFD, 94 0x3FBC0000, 0xAB2E5990, 0x3FBBE39F, 0x679755D8, 0x3B5AF7C1, 0xBBB2A139, 95 0x3FC00000, 0x7F748304, 0x3FBFD5BB, 0x95A94110, 0x3B5B0A0C, 0x811C880E, 96 0x3FC20000, 0x3DF2157F, 0x3FC1E1FB, 0x37C2C7E5, 0x3B617207, 0xB776AF4F, 97 0x3FC40000, 0x30754446, 0x3FC3D6EF, 0x1814018D, 0xBB63A092, 0x88503B16, 98 0x3FC60000, 0x7996ECD4, 0x3FC5C981, 0x94588C25, 0xBB5B6979, 0x558D8B64, 99 0x3FC80000, 0x76D31B22, 0x3FC7B97B, 0xBE985C07, 0x3B6708AD, 0xCC1C4519, 100 0x3FCA0000, 0xEADCE47A, 0x3FC9A6A9, 0xCAFAF9A8, 0x3B62971C, 0xA562CA82, 101 0x3FCC0000, 0x7E8C3F27, 0x3FCB90D7, 0xCB57348B, 0xBB493C17, 0xA875159C, 102 0x3FCE0000, 0x5B063A6A, 0x3FCD77D6, 0x3569311A, 0xBB5A33AB, 0xA192F16A, 103 0x3FD00000, 0x64EF22FF, 0x3FCF5B76, 0xB72AE095, 0x3B52E368, 0xB50909D6, 104 0x3FD10000, 0x87DE9AAA, 0x3FD09DC6, 0x16C29778, 0xBB55B0DC, 0xF3418D68, 105 0x3FD20000, 0x0AAD7C84, 0x3FD18BF5, 0xACF10E71, 0x3B41EAC1, 0x346154B4, 106 0x3FD30000, 0x1D92088F, 0x3FD27837, 0x3B84D2FF, 0x3B48BBE9, 0xDC9998E5, 107 0x3FD40000, 0xCC4E6285, 0x3FD36277, 0xF12910F6, 0xBB6585F3, 0xFA8B319B, 108 0x3FD50000, 0x766A7592, 0x3FD44AA4, 0xA1AA8D78, 0x3B6C6289, 0x13F656CF, 109 0x3FD60000, 0xCFA33544, 0x3FD530AE, 0x5303BB5D, 0x3B63F533, 0xC1117E20, 110 0x3FD70000, 0xC925EED6, 0x3FD61484, 0xB52DF321, 0xBB70059A, 0x66E93FA9, 111 0x3FD80000, 0x54AA10D9, 0x3FD6F619, 0x8C1ECA84, 0x3B60C60C, 0x08BED883, 112 0x3FD90000, 0x113AC5B7, 0x3FD7D560, 0x5A568BA4, 0xBB541817, 0xB5654BFC, 113 0x3FDA0000, 0x6D101F2E, 0x3FD8B24D, 0x96E71249, 0xBB55A721, 0x1379C827, 114 0x3FDB0000, 0xE246C017, 0x3FD98CD6, 0x05641F92, 0x3B6918FF, 0xCA4E1DF9, 115 0x3FDC0000, 0x39B58346, 0x3FDA64EE, 0xF43C341A, 0x3B6633D0, 0xEECC747A, 116 0x3FDD0000, 0x4C36F71C, 0x3FDB3A91, 0x5CE1B431, 0xBB61E754, 0x0B1A4FB4, 117 0x3FDE0000, 0x66CA921B, 0x3FDC0DB5, 0x1D94F195, 0x3B571DE1, 0xE6981964, 118 0x3FDF0000, 0x3AD3639E, 0x3FDCDE53, 0x72D1AC94, 0xBB736718, 0x370B3962, 119 0x3FE00000, 0x7815CCCD, 0x3FDDAC67, 0xC5849B77, 0x3B52FF7C, 0xC7D84489, 120 0x3FE08000, 0xF40DDDFC, 0x3FDE77ED, 0x00AEBFCD, 0x3B62E958, 0xE33FF707, 121 0x3FE10000, 0xA6C93DAD, 0x3FDF40DE, 0x0F7AA915, 0x3B77641D, 0x15CA0475, 122 0x3FE18000, 0x85EBF4D7, 0x3FE0039C, 0xDAD8BEF9, 0x3B722996, 0x8391BF09, 123 0x3FE20000, 0xC129DA76, 0x3FE0657F, 0x27977717, 0xBB761869, 0xC045B9BD, 124 0x3FE28000, 0x93F751BC, 0x3FE0C614, 0xCA41B0AE, 0xBB7A8A92, 0x3C961154, 125 0x3FE30000, 0x7C1EF6CE, 0x3FE1255D, 0xF7C0A55C, 0x3B591CBF, 0x478B1C38, 126 0x3FE38000, 0x169FA349, 0x3FE1835A, 0x993DD546, 0x3B6FBFAB, 0x698175A0, 127 0x3FE40000, 0x27D6B511, 0x3FE1E00B, 0xC884E585, 0xBB248C8D, 0x9BB39A1C, 128 0x3FE48000, 0x6BE89876, 0x3FE23B72, 0x2F4EF788, 0xBB815690, 0x7DF099CF, 129 0x3FE50000, 0x280F4ABE, 0x3FE2958E, 0x7530C25F, 0xBB72B7E0, 0xEE07EAE7, 130 0x3FE58000, 0x2FEDFD47, 0x3FE2EE62, 0xA50C9A07, 0xBB2B522D, 0xBFFA3A8C, 131 0x3FE60000, 0x875C63BA, 0x3FE345F0, 0x78B8C001, 0xBB408ED6, 0xD056E4C4, 132 0x3FE68000, 0x8A368DBA, 0x3FE39C39, 0x79511750, 0x3B77CB64, 0x0C777681, 133 0x3FE70000, 0xEE7CA285, 0x3FE3F140, 0x55DECB32, 0xBB5AA9DC, 0xBC68CF79, 134 0x3FE78000, 0xA4904A32, 0x3FE44506, 0xC661B510, 0x3B7EBCE3, 0x3EB6C0CD, 135 0x3FE80000, 0x4CA9F6E2, 0x3FE4978F, 0xD4373CAA, 0x3AFF9675, 0xAB73F345, 136 0x3FE88000, 0xD7B95553, 0x3FE4E8DE, 0xE3B770C7, 0xBB715BD3, 0xBFA6C0AD, 137 0x3FE90000, 0x849C7E04, 0x3FE538F5, 0xCDE27023, 0xBB6B45C2, 0x3E5A5CC8, 138 0x3FE98000, 0xC171C662, 0x3FE587D8, 0x95C38C2E, 0x3B7887A1, 0x345B0752, 139 0x3FEA0000, 0x4321104C, 0x3FE5D589, 0xAF86142F, 0xBB8438EB, 0x1AE94AC1, 140 0x3FEA8000, 0x838D8D26, 0x3FE6220D, 0x5F66C783, 0x3B7CA422, 0x8F96E72F, 141 0x3FEB0000, 0xE4DA897E, 0x3FE66D66, 0xBED2B224, 0xBB35FB4D, 0xFD76AD75, 142 0x3FEB8000, 0xD775765C, 0x3FE6B799, 0x0DF9D017, 0x3B7B5383, 0xE0D80102, 143 0x3FEC0000, 0xAA053CA7, 0x3FE700A8, 0x25C3BB63, 0xBB7D5234, 0x29157DFC, 144 0x3FEC8000, 0x773AAC9B, 0x3FE74897, 0xD237C658, 0x3B6ACFB2, 0xF4E46A15, 145 0x3FED0000, 0x3FA5ABCF, 0x3FE78F6B, 0xE04F6C27, 0xBB8680F4, 0x55D1C7DF, 146 0x3FED8000, 0xD31E46AA, 0x3FE7D528, 0x9AC0235F, 0xBB61A1B0, 0x1EABC199, 147 0x3FEE0000, 0xBB676A41, 0x3FE819D1, 0x1AD33A87, 0xBB7726EA, 0x735248A8, 148 0x3FEE8000, 0x76CB5B54, 0x3FE85D69, 0x95ABE3CC, 0x3B772D9C, 0x044A3CEB, 149 0x3FEF0000, 0x26506206, 0x3FE89FF6, 0x131BC92E, 0x3B860889, 0x51E5F051, 150 0x3FEF8000, 0xED69BF50, 0x3FE8E17B, 0x2230274E, 0xBB7FB7C5, 0x5CA2A11A, 151 152 //******************************************************************* 153 // Accurate table over range ( 1.000000, 1.968750). * 154 //******************************************************************* 155 156 0x3FF00000, 0x38A5805B, 0x3FE921FB, 0x8CE9AD0F, 0xBB728518, 0x56659FDA, 157 0x3FF08000, 0xE4CDB94C, 0x3FE9A001, 0x86F9991F, 0xBB7F4F21, 0xC242FD58, 158 0x3FF10000, 0x29DA60EA, 0x3FEA1A26, 0x1A19C30A, 0xBB87F5DE, 0xE73B7B3A, 159 0x3FF18000, 0x9BBB03C5, 0x3FEA908B, 0x882B14EE, 0x3B8A364F, 0xC319894C, 160 0x3FF20000, 0x42A338B5, 0x3FEB034F, 0x7337C8D1, 0xBB768B38, 0xD9BDAC43, 161 0x3FF28000, 0xED0428FC, 0x3FEB7292, 0x7FBAC8B6, 0x3B7B400A, 0x53FD9AAF, 162 0x3FF30000, 0x36946784, 0x3FEBDE71, 0x1A8E3A61, 0x3B6C2B37, 0x13D123E1, 163 0x3FF38000, 0x21F16647, 0x3FEC470A, 0xDA7DBAA7, 0xBB523353, 0xD7A5886A, 164 0x3FF40000, 0xF06227B4, 0x3FECAC7D, 0x132231D2, 0xBB8AEFE3, 0x0558B34B, 165 0x3FF48000, 0xF9AB1CF7, 0x3FED0EE2, 0xE23FB012, 0xBB4465DC, 0xD4A6C05D, 166 0x3FF50000, 0x1DAE2F90, 0x3FED6E57, 0xE51C7E16, 0xBB85A9B9, 0x83503D52, 167 0x3FF58000, 0xD679A51F, 0x3FEDCAF8, 0xC6A4C801, 0x3B8576BE, 0xCEAEFC33, 168 0x3FF60000, 0xCE367C5E, 0x3FEE24DD, 0xD375A188, 0xBB78F5B1, 0x1E4802A0, 169 0x3FF68000, 0xCD05D052, 0x3FEE7C20, 0xCBEB8A43, 0xBB8AD216, 0x43D5F156, 170 0x3FF70000, 0x98AA0697, 0x3FEED0D9, 0xE022B144, 0x3B267908, 0xB6C976B5, 171 0x3FF78000, 0xA3FB1493, 0x3FEF2320, 0xDB8F1029, 0xBB85B081, 0x83128CFA, 172 0x3FF80000, 0x681E0063, 0x3FEF730C, 0x12946C3F, 0xBB8AA69F, 0xBF359098, 173 0x3FF88000, 0x75E901B6, 0x3FEFC0B1, 0xB86DE15F, 0x3B8EAA0C, 0x4663839A, 174 0x3FF90000, 0x736A4590, 0x3FF00613, 0x4FBE5B7E, 0xBB4E3551, 0x42306F18, 175 0x3FF98000, 0xC5B189FC, 0x3FF02ABF, 0xA107BE50, 0x3B63FD1C, 0xCE1D6AEB, 176 0x3FFA0000, 0x41411D33, 0x3FF04E67, 0x3966892F, 0xBB86ED08, 0x00B1EF7B, 177 0x3FFA8000, 0x4DDFE3DA, 0x3FF07113, 0xDB772C28, 0x3B746CEB, 0x807EA687, 178 0x3FFB0000, 0xA7AB4BE2, 0x3FF092CE, 0x72AC060E, 0xBB72F0AF, 0x054AD94E, 179 0x3FFB8000, 0x35EE2E87, 0x3FF0B39F, 0x5C6DBFD7, 0xBB8A699D, 0x14CF8D89, 180 0x3FFC0000, 0x79493CCE, 0x3FF0D38F, 0x4A3683E2, 0xBB7C178E, 0x4E0FB167, 181 0x3FFC8000, 0x7C2C16CD, 0x3FF0F2A5, 0xF7C1C52E, 0xBB77BBEC, 0x0F5FF2D9, 182 0x3FFD0000, 0xF7925B8C, 0x3FF110EB, 0x3A456E0E, 0x3B86B850, 0xB94665FD, 183 0x3FFD8000, 0xD4EDAFAA, 0x3FF12E66, 0x2A98E0EA, 0x3B8FC04D, 0xF88FF47B, 184 0x3FFE0000, 0x1822F5F9, 0x3FF14B1D, 0xDB5166C5, 0x3B400FEE, 0xA21D9DDA, 185 0x3FFE8000, 0x5F375D4F, 0x3FF16719, 0x6EAC8C79, 0xBB45D7BA, 0x99C8508E, 186 0x3FFF0000, 0x983AF36D, 0x3FF1825F, 0x2745DBAE, 0xBB8849C2, 0x328CE199, 187 0x3FFF8000, 0xDF7044EE, 0x3FF19CF5, 0x48D90CBC, 0xBB876AC4, 0x23C76E06, 188 189 //****************************************************************** 190 // Accurate table over range ( 2.000000, 2.937500). * 191 //****************************************************************** 192 193 0x40000000, 0xC89A22AD, 0x3FF1B6E1, 0xE3296298, 0xBB83E57A, 0x4E33C68C, 194 0x40008000, 0xAE85BCDD, 0x3FF1E8D4, 0xB635433E, 0x3B8FDE86, 0xD38237A1, 195 0x40010000, 0x1E66B4AD, 0x3FF21862, 0xFF00ECE6, 0x3B74E47A, 0x940D38B0, 196 0x40018000, 0x257005B2, 0x3FF245B5, 0x07E38198, 0xBB90341D, 0xF7AEB5A2, 197 0x40020000, 0x55656B58, 0x3FF270EF, 0x71D13D73, 0x3B88C680, 0x13906BD2, 198 0x40028000, 0x466225D9, 0x3FF29A34, 0x0FA8F5E6, 0x3B91F854, 0xF983041D, 199 0x40030000, 0x717EC3D3, 0x3FF2C1A2, 0x640509A5, 0x3B8E1C75, 0xAF6F1BFF, 200 0x40038000, 0x75A7B542, 0x3FF2E757, 0x4A697F72, 0x3B92AB3B, 0x412F53FB, 201 0x40040000, 0x00512EF1, 0x3FF30B6D, 0x7980B2E2, 0x3B8AD702, 0x40329E0C, 202 0x40048000, 0x09ED9B8A, 0x3FF32DFE, 0x0460EC6D, 0x3B6B92BF, 0x54B284E9, 203 0x40050000, 0x1B9F04CA, 0x3FF34F1F, 0xC21A2D1B, 0xBB82C1A6, 0xD9CE49BA, 204 0x40058000, 0x697C1A2B, 0x3FF36EE8, 0x0C4A7DD1, 0x3B73DD4E, 0x5C021394, 205 0x40060000, 0xABB8A398, 0x3FF38D6A, 0x94FD5FEE, 0x3B373349, 0x3B4FC3A6, 206 0x40068000, 0x18374FED, 0x3FF3AAB9, 0x8BB1767A, 0x3B72834E, 0xCBC4CA13, 207 0x40070000, 0xBCD94FDA, 0x3FF3C6E6, 0x7976E8D9, 0xBB931322, 0x7228DCD0, 208 0x40078000, 0x7BA476B6, 0x3FF3E200, 0xC84E84B4, 0xBB87D21A, 0xC44FB391, 209 210 //****************************************************************** 211 // Accurate table over range ( 3.000000, 3.875000). * 212 //****************************************************************** 213 214 0x40080000, 0xD7180754, 0x3FF3FC17, 0x967F5249, 0xBB64B771, 0x5FA0957B, 215 0x40090000, 0x6DFDCD42, 0x3FF42D70, 0x558EAD29, 0x3B84B923, 0xDD410F01, 216 0x400A0000, 0xE7C427AE, 0x3FF45B54, 0xAB8A2C51, 0x3B91D694, 0xE38B7BFF, 217 0x400B0000, 0x10E3223E, 0x3FF4861B, 0x4FB5B5B4, 0xBB7CB027, 0x50BA194A, 218 0x400C0000, 0x8EA13F5E, 0x3FF4AE11, 0x11ECF83F, 0x3B8B6616, 0xD89A7B16, 219 0x400D0000, 0x06D105F7, 0x3FF4D378, 0xC2906964, 0x3B93659C, 0x0737481A, 220 0x400E0000, 0x727DD5BC, 0x3FF4F68D, 0xF99AE908, 0x3B8514AE, 0x4636F80B, 221 0x400F0000, 0x3FDFD1C5, 0x3FF51785, 0x020F4064, 0xBB65DB78, 0x8577ADC5, 222 223 //****************************************************************** 224 // Accurate table over range ( 4.000000, 5.750000). * 225 //****************************************************************** 226 227 0x40100000, 0xCF49E240, 0x3FF5368C, 0xC5E4B1C8, 0xBB5E5499, 0xA9C4BF51, 228 0x40110000, 0x94E90733, 0x3FF56F6F, 0x52E31047, 0x3B8F3B21, 0x724AC4D7, 229 0x40120000, 0x46578102, 0x3FF5A250, 0x5F4EF405, 0x3B8657A1, 0x1EBE66F0, 230 0x40130000, 0xCA3D6D0F, 0x3FF5D013, 0xE66FF8CA, 0x3B60B423, 0x26CAA3CA, 231 0x40140000, 0x32964FAE, 0x3FF5F973, 0x1CEDA34B, 0x3B635D66, 0xC3ED1C18, 232 0x40150000, 0xA6AA4915, 0x3FF61F06, 0xDE005085, 0x3B6E8C7F, 0x000B0CDD, 233 0x40160000, 0x8906EAE3, 0x3FF6414D, 0x5593660A, 0x3B95FADD, 0xB8BF7A98, 234 0x40170000, 0x831FA60C, 0x3FF660B0, 0x3BD94D47, 0x3B96491D, 0x5B9C83F6, 235 236 //****************************************************************** 237 // Accurate table over range ( 6.000000, 7.500000). * 238 //****************************************************************** 239 240 0x40180000, 0x8DCF9463, 0x3FF67D88, 0x73114F7D, 0x3B928119, 0xC1230051, 241 0x401A0000, 0xCBB9EEAD, 0x3FF6B0BA, 0xFB083C0D, 0x3B93280F, 0xAE0D69E3, 242 0x401C0000, 0xDEF559E1, 0x3FF6DCC5, 0x8D8B9598, 0x3B86722D, 0x1022C04A, 243 0x401E0000, 0x744BF1EC, 0x3FF7030D, 0x01605442, 0xBB736E8B, 0xF92A87CA, 244 245 //****************************************************************** 246 // Accurate table over range ( 8.000000, 12.000000). * 247 //****************************************************************** 248 249 0x40200000, 0x456D4528, 0x3FF7249F, 0xB324E4B7, 0x3B675690, 0xDD79F342, 250 0x40220000, 0x43E2466D, 0x3FF75CBA, 0xD9437CC1, 0x3B46FCCD, 0xEB45ACCD, 251 0x40240000, 0x18A681EA, 0x3FF789BD, 0x2E09D7EA, 0x3B6C324D, 0xB28DD9D9, 252 0x40260000, 0xF3FE273A, 0x3FF7AEA3, 0x9C1AAC21, 0x3B8D6F66, 0xFC2D1461, 253 0x40280000, 0x455A6241, 0x3FF7CD6F, 0x71992B07, 0x3B8B2FE8, 0xBAEBACBC, 254 0x40280000, 0x455A6241, 0x3FF7CD6F, 0x71992B07, 0x3B8B2FE8, 0xBAEBACBC 255}; 256 257struct atantblEntry { 258 double One; 259 double Two; 260 double Three; 261} atantblEntry; 262 263long double atanl( long double x ) 264{ 265 double p1, p2, p3, p2a, p4, p5, p6, p7, p8, p29, p30, p33, p35; 266 double quot, quot2; 267 double rarg, result, restemp; 268 double top, top2, topextra, top3; 269 double bot, bot2; 270 double r, rarg2, rarg2a; 271 double temps; 272 double remainder, residual; 273 double partial; 274 double arg, argl, argsq, argsq2; 275 double temp,temp2; 276 double sum, sumt, suml; 277 double absx; 278 double xHead, xTail; 279 double res, reslow, resmid, restiny, reshi, resbot; 280 double p, q; 281 double prod, prodlow; 282 Double DeN ; 283 double fenv; 284 DblDbl ddx; 285 int i, rflag; 286 uint32_t index; 287 288 struct atantblEntry *atanPtr = (struct atantblEntry *)atanTable - 6; 289 290 FEGETENVD(fenv); 291 FESETENVD(0.0); 292 293 ddx.f = x; 294 xHead = ddx.d[0]; 295 xTail = ddx.d[1]; 296 297 // x is a NaN or zero 298 299 if ((xHead != xHead)||(xHead == 0.0)) { // x is 0 or a NaN 300 FESETENVD(fenv); 301 return x; 302 } 303 304 // x is not a NaN nor zero 305 306 absx = fabs(xHead); 307 308 //finite result 309 310 //*************************************************************************** 311 // This routine breaks the arguments into five ranges: * 312 // Range 1: 0 <= |x| <= .0859375 * 313 // Range 2: .0859375 <= |x| <= 1.015625 * 314 // Range 3: 1.015625 <= |x| < 13 * 315 // Range 4: 13 <= |x| < 2^107 * 316 // Range 5: 2^107 <= |x| <= Infinity * 317 // * 318 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * 319 // * 320 // In Range 1, a 15th degree polynomial in x^2 is used to evaluate QATAN. * 321 // * 322 // In Range 2 and, * 323 // In Range 3 the accurate table method is used to range-reduce the * 324 // argument to a small value to be used with an interpolating * 325 // polynomial for QATAN. In Ranges 2 and 3, the resultant * 326 // argument is less than 2^-7, so an 8th degree polynomial can * 327 // be used. Range 3 requires additional work to find the * 328 // correct index into the accurate table. * 329 // * 330 // In Range 4, QATAN(x) = Pi/2 - QATAN(1/x). After taking the reciprocal * 331 // of the argument, the quotient is less than 1/13, so that the * 332 // 15th degree polynomial used for Range 1 is used to compute * 333 // QATAN(1/x) * 334 // * 335 // In Range 5, the correctly rounded value differs from Pi/2 by less than * 336 // 1/2 ulp. It is, however, incorrect to let the value become * 337 // correctly rounded, as that correctly rounded value exceeds * 338 // PI/2 and is in the wrong quadrant. Applying the inverse * 339 // function, QTAN, to the correctly rounded value of PI/2 would * 340 // produce a result of the opposite sign to the argument * 341 // originally given to ATAN. * 342 //*************************************************************************** 343 344 // Range 5 345 346 if (absx >= kLimit4) { // Filter out unusual arguments 347 ddx.d[0] = kPiBy2; 348 ddx.d[1] = kPiBy2Tail1m; // Intentional misround to 349 if (xHead < 0.0) { 350 ddx.d[0] = -ddx.d[0]; 351 ddx.d[1] = -ddx.d[1]; 352 } 353 FESETENVD(fenv); 354 return (ddx.f); 355 } 356 357 // Ranges 1 and 4 (DO NOT USE TABLE) 358 359 rflag = 0; 360 361 // Range 4 362 363 if (absx >= kLimit3) { // Range 4 364 rarg = 1.0/xHead; 365 rflag = 1; // indicate large argument 366 p1 = __FNMSUB( xHead, rarg, 1.0 ); // 1.0 - xHead*rarg; // time to complete hi precision 367 p2 = xTail*rarg; // reciprocal of argument, to 368 p3 = p1 - p2; // use as reduced argument. 369 rarg2a = p3*rarg; 370 rarg2 = rarg2a + __FNMSUB( xHead, rarg2a, p3 )*rarg; // rarg2a + (p3 - xHead*rarg2a)*rarg; 371 xHead = rarg; 372 xTail = rarg2; 373 } 374 375 // Ranges 1 and 4 only 376 377 if( (absx < kLimit1) || (absx >= kLimit3) ) { // Code for Range 1 and Range 4 378 temp = 2.0*xHead*xTail; // direct evaluation of series 379 argsq = __FMADD( xHead, xHead, temp ); // xHead*xHead + temp; // compute square of argument 380 argsq2 = __FMADD( xTail, xTail, __FMSUB( xHead, xHead, argsq ) + temp ); // xHead*xHead - argsq + temp + xTail*xTail; 381 sum = atancoeff[14]; 382 sum = __FMADD( argsq, sum, atancoeff[13] ); // atancoeff[13] + argsq*sum; 383 sum = __FMADD( argsq, sum, atancoeff[12] ); // atancoeff[12] + argsq*sum; 384 sum = __FMADD( argsq, sum, atancoeff[11] ); // atancoeff[11] + argsq*sum; 385 sumt = __FMADD( argsq, sum, atancoeff[10] ); // atancoeff[10] + argsq*sum; 386 sum = __FMADD( argsq, sum, atancoeff[9] ); // atancoeff[9] + argsq*sumt; 387 suml = __FMADD( argsq, sumt, atancoeff[9] - sum ); // atancoeff[9] - sum + argsq*sumt; 388 389 for (i = 8; i >= 1; i--) { 390 temps = __FMADD( argsq, sum, atancoeff[i] ); // atancoeff[i] + sum*argsq; 391 /* suml = atancoeff[i] - temps+sum*argsq + (sum*argsq2 + suml*argsq); */ 392 suml = __FMADD( sum, argsq, atancoeff[i] - temps ) + __FMADD( sum, argsq2, suml*argsq ); 393 sum=temps; 394 } 395 396 prodlow = __FMADD( suml, argsq, sum*argsq2 ); // suml*argsq + sum*argsq2; // multiply by arg^2 397 prod = __FMADD( sum, argsq, prodlow ); // sum*argsq + prodlow; 398 prodlow = __FMSUB( sum, argsq, prod ) + prodlow; // sum*argsq - prod + prodlow; 399 temp2 = __FMADD( prodlow, xHead, prod*xTail ); // prodlow*xHead + prod*xTail; // multiply by arg 400 temp = __FMADD( prod, xHead, temp2 ); // prod*xHead + temp2; 401 temp2 = __FMSUB( prod, xHead, temp ) + temp2; // prod*xHead - temp + temp2; 402 sum = temp*kRecip; // sum of series --- 403 remainder = __FNMSUB( sum, atancoeff[0], temp ); // (temp - sum*atancoeff[0]); 404 partial = __FADD( remainder, temp2 ); 405 residual = remainder - partial + temp2; 406 suml = __FMADD( partial, kRecip, (residual*kRecip) );// partial*kRecip + (residual*kRecip); 407 res = __FADD( xHead, sum ); // except for argument 408 reslow = (xHead - res + sum); // exact 409 resmid = __FADD( xTail, suml ); 410 restiny = xTail - resmid + suml; 411 p = __FADD( reslow, resmid ); // sum of middle terms 412 q = reslow - p + resmid; // possible residual 413 reshi = res + p; 414 resbot = (res - reshi + p) + (q + restiny); 415 if (rflag == 1) { // large magnitude argument 416 if (xHead > 0) { // fetch pi/2 with proper sign 417 p1 = kPiBy2; 418 p2 = kPiBy2Tail1; 419 p2a = kPiBy2Tail2; 420 } 421 else { 422 p1 = -kPiBy2; 423 p2 = -kPiBy2Tail1; 424 p2a = -kPiBy2Tail2; 425 } 426 p3 = __FSUB( p1, reshi ); // subtract result from pi/2 427 p4 = p1 - p3 - reshi; 428 p5 = __FSUB( p2, resbot ); 429 p6 = p2 - p5 - resbot + p2a; 430 p7 = __FADD( p4, p5 ); 431 reshi = __FADD( p3, p7 ); 432 if (fabs(p4) > fabs(p5)) 433 p8 = p4 - p7 + p5; 434 else 435 p8 = p5 - p7 + p4; 436 437 resbot = p3 - reshi + p7 + (p6 + p8 - restiny); 438 } 439 ddx.d[0] = __FADD( reshi, resbot ); 440 ddx.d[1] = (reshi - ddx.d[0]) + resbot; 441 442 FESETENVD(fenv); 443 return (ddx.f); 444 } 445 446 // Ranges 2 and 3 (USE TABLE) 447 448 //if( (absx >= kLimit1) || (absx < kLimit3) ) { // Code for Range 2 and Range 3 449 450 // Note 1: The above statement in the Taligent code always tests true. Logically, 451 // it was probably intended that || be &&. This would make the test logically 452 // equivalent to an "else" clause for the previous if. Replacing with an else 453 // also eliminates the problem of a code path that avoids any return statements 454 // (as detected by MrC as a compiler warning). PAF 455 else { 456 457 DeN.f = __FMADD( 64.0, absx, kBig ); // 64.0*absx + kBig; 458 459 if (absx > kLimit2) { // for large args, use recip. Range 3 460 FESETENVD(kBig+1.0); // use trunc mode momentarily 461 DeN.f = absx + kBig; // determine range of argument 462 FESETENVD(kBig+1.0); // use trunc mode momentarily 463 DeN.f = absx + kBig; // determine range of argument 464 FESETENVD(kBig); // return to round-to-nearest 465 index = DeN.i[1]; 466 i = index - 1; 467 DeN.f = __FMADD( factor[i], absx, kBig + adjust[i] ); // factor[i]*absx + kBig + adjust[i]; 468 } 469 470 index = DeN.i[1]; 471 472 if (xHead < 0) { // use abs. value 473 arg = -xHead; 474 argl = -xTail; 475 } 476 else { 477 arg = xHead; 478 argl = xTail; 479 } 480 481 top = __FSUB( arg, atanPtr[(int32_t)index].One ); 482 top2 = __FADD( top, argl ); 483 topextra = arg - top - atanPtr[(int32_t)index].One; 484 top3 = top - top2 + argl + topextra; // reduced numerator 485 bot =__FMADD( arg, atanPtr[(int32_t)index].One, 1.0 ); // 1.0 + arg*atanPtr[(int32_t)index].One; 486 /* bot2 = 1.0 - bot + arg*atanPtr[(int32_t)index].One + 487 argl*atanPtr[(int32_t)index].One; */ // denominator 488 bot2 = __FMADD( argl, atanPtr[(int32_t)index].One, __FMADD( arg, atanPtr[(int32_t)index].One, 1.0 - bot ) ); 489 r = 1.0/bot; 490 quot = r*top2; 491 quot = __FMADD( __FNMSUB( bot, quot, top2), r, quot ); // quot + (top2 - bot*quot)*r; 492 493 p29 = __FNMSUB( bot, quot, top2); // top2 - quot*bot; 494 p30 = quot*bot2; // negative term 495 p33 = p29 - p30; 496 p35 = p33 + top3; 497 quot2 = p35*r; 498 quot2 = __FMADD( __FNMSUB( quot2, bot, p35 ), r, quot2 ); // quot2 + (p35 - quot2*bot)*r; // second fraction wd. 499 temp = 2.0*quot*quot2; // reduced arg is (quot,quot2) 500 argsq = __FMADD( quot, quot, temp ); // quot*quot + temp; // compute square of argument 501 argsq2 = __FMADD( quot2, quot2, __FMSUB( quot, quot, argsq) + temp ); // quot*quot - argsq + temp + quot2*quot2; 502 sumt = __FMADD( argsq, atancoeff[7], atancoeff[6] );// atancoeff[6] + argsq*atancoeff[7]; 503 sum = __FMADD( argsq, sumt, atancoeff[5] ); // atancoeff[5] + argsq*sumt; 504 suml = __FMADD( argsq, sumt, atancoeff[5] - sum ); // atancoeff[5] - sum + argsq*sumt; 505 506 for (i = 4; i >= 1; i--) { 507 temps = __FMADD( sum, argsq, atancoeff[i] ); // atancoeff[i] + sum*argsq; 508 /* suml = atancoeff[i] - temps + sum*argsq + (sum*argsq2 + suml*argsq); */ 509 suml = __FMADD( sum, argsq, atancoeff[i] - temps ) + __FMADD( sum, argsq2, suml*argsq ); 510 sum = temps; 511 } 512 513 prodlow = __FMADD( suml, argsq, sum*argsq2 ); // suml*argsq + sum*argsq2; // mult. by arg^2 514 prod = __FMADD( sum, argsq, prodlow ); // sum*argsq + prodlow; 515 prodlow = __FMSUB( sum, argsq, prod ) + prodlow; // sum*argsq - prod + prodlow; 516 temp2 = __FMADD( prodlow, quot, prod*quot2 ); // prodlow*quot + prod*quot2; // mult. by arg 517 temp = __FMADD( prod, quot, temp2 ); // prod*quot + temp2; 518 temp2 = __FMSUB( prod, quot, temp ) + temp2; // prod*quot - temp + temp2; 519 sum = temp*kRecip; // sum of series --- 520 remainder = __FNMSUB( sum, atancoeff[0], temp ); // (temp - sum*atancoeff[0]); 521 partial = __FADD( remainder, temp2 ); 522 residual = remainder - partial + temp2; 523 suml = __FMADD( partial, kRecip, (residual*kRecip) ); // partial*kRecip + (residual*kRecip); 524 res = __FADD( quot, sum ); // except for argument 525 reslow = (quot - res + sum); // exact 526 resmid = __FADD( quot2, suml ); 527 restiny = quot2 - resmid + suml; 528 p = __FADD( reslow, resmid ); // sum of middle terms 529 q = reslow - p + resmid; // possible residual 530 reshi = __FADD( res, p ); 531 resbot = (res - reshi + p) + (q + restiny); 532 result = __FADD( atanPtr[(int32_t)index].Two, reshi ); 533 reslow = __FADD( atanPtr[(int32_t)index].Three, resbot ); 534 resmid = atanPtr[(int32_t)index].Two - result + reshi; 535 restiny = resbot - reslow + atanPtr[(int32_t)index].Three; 536 restemp = __FADD( resmid, reslow ); 537 reshi = __FADD( result, restemp ); 538 539 if (fabs(resmid) > fabs(reslow)) 540 restiny = resmid - restemp + reslow + restiny; 541 else 542 restiny = reslow - restemp + resmid + restiny; 543 544 resbot = result - reshi + restemp + restiny; 545 546 if (xHead < 0.0) { 547 reshi = -reshi; 548 resbot = -resbot; 549 result = -result; 550 restemp = -restemp; 551 restiny = -restiny; 552 } 553 554 ddx.d[0] = __FADD( reshi, resbot ); 555 ddx.d[1] = (reshi - ddx.d[0]) + resbot; 556 557 FESETENVD(fenv); 558 return (ddx.f); // Normal arguments done 559 } 560} 561 562// End of atanl, start of atan2l: 563 564//******************************************************************************* 565// _QATAN2 expects two quad words as arguments. It returns the arctan * 566// of the quotient of the arguments, but differs from _QATAN in that * 567// the result can be in the interval [-Pi,Pi], whereas _QATAN always * 568// returns a result in the range [-Pi/2, Pi/2]. After argument reduction * 569// and the testing of numerous special cases, _QATAN is used for the bulk * 570// of the work. * 571// * 572// atan2(NaN, anything)---------------------------------> NaN * 573// atan2(anything, NaN)---------------------------------> NaN * 574// atan2(+-0, +(anything but NaN))----------------------> +-0 * 575// atan2(+-0, -(anything but NaN))----------------------> +-Pi * 576// atan2(+-(anything but 0 and NaN), 0 )----------------> +-Pi/2 * 577// atan2(+-(anything but Infinity and NaN), +Infinity)--> +-0 * 578// atan2(+-(anything but Infinity and NaN), -Infinity)--> +-Pi * 579// atan2(+-Infinity, +Infinity)-------------------------> +-Pi/4 * 580// atan2(+-Infinity, -Infinity)-------------------------> +-3Pi/4 * 581// atan2(+-Infinity, (anything but 0, NaN, Infinity))---> +-Pi/2 * 582// * 583//******************************************************************************* 584 585// Floating-point constants 586static const double kTiny = 1.805194375864829576e-276; // 0x1.0p-916 = 0x06B00000 587// kTiny: number that still allows a 107 bit quad to consist of two normal numbers 588 589static const double kRescale = 2.923003274661805836e+48; // 0x1.0p+161 590// Needed to rescale if the denominator is "tiny" 591 592static const double kPi = 3.141592653589793116; // 0x1.921FB54442D18p1 593static const double kPiTail1 = 1.224646799147353207e-16; // 0x1.1A62633145C07p-53 594static const double kPiTail1m = 1.224646799147352961e-16; // 0x1.1A62633145C06p-53 595static const double kPiTail2 = -2.994769809718339666e-33; // 0x1.F1976B7ED8FBCp-109 596 597static const double k3PiBy4 = 2.356194490192344837; // 0x1.2D97C7F3321D2p1 598static const double k3PiBy4Tail1 = 9.184850993605148438e-17;// 0x1.A79394C9E8A0Ap-54 599 600 601long double atan2l( long double y, long double x ) 602{ 603 double p1, p2, p3, p2a, p4, p5, p6, p7, p8, p29, p30, p33, p35; 604 double p31, p32, p34, p36, p37, p38; 605 double quot, quot2; 606 double rarg, result, restemp; 607 double top, top2, topextra, top3; 608 double extra; 609 double bot, bot2; 610 double r, rarg2, rarg2a; 611 double temps; 612 double remainder, residual; 613 double partial; 614 double arg, argl, argsq, argsq2; 615 double temp,temp2; 616 double sum, sumt, suml; 617 double absx; 618 double xHead, xTail; 619 double res, reslow, resmid, restiny, reshi, resbot; 620 double p, q; 621 double prod, prodlow; 622 double xDen, xDenTail, yNum, yNumTail; 623 double frac3, frac2, frac, fract; 624 double pin, pin2, pin3; 625 double ressmall, restop, resint; 626 Double DeN ; 627 double fpenv; 628 DblDbl ddx, ddy; 629 630 int i, rflag; 631 632 uint32_t index; 633 uint32_t signx, signy, expx, expy, sigx, sigy; 634 635 struct atantblEntry *atanPtr = (struct atantblEntry *)atanTable - 6; 636 637 FEGETENVD(fpenv); 638 FESETENVD(0.0); 639 640 ddx.f = x; // denominator 641 ddy.f = y; // numerator 642 643 xDen = ddx.d[0]; // dden 644 xDenTail = ddx.d[1]; // ddenl 645 yNum = ddy.d[0]; // dnum 646 yNumTail = ddy.d[1]; // dnuml 647 648 expy = (ddy.i[0] >> 20) & 0x7ffu; 649 expx = (ddx.i[0] >> 20) & 0x7ffu; // get biased exponents 650 signy = (ddy.i[0] >> 31) & 1u; 651 signx = (ddx.i[0] >> 31) & 1u; // get signs 652 sigy = (ddy.i[0] & 0xfffffu) | ddy.i[1]; 653 sigx = (ddx.i[0] & 0xfffffu) | ddx.i[1]; 654 655 if (expy == 0x7ffu) { // y is infinite or NaN 656 if (sigy != 0) { 657 FESETENVD(fpenv); 658 return (y); // NaN y is returned 659 } 660 else if (expx == 0x7ffu) { // infinite y 661 if (sigx != 0) { 662 FESETENVD(fpenv); 663 return (x); // NaN x is returned 664 } 665 else if (signx == 0) { // infinite y and x denominator positive 666 if (signy) { // numerator negative 667 ddx.d[0] = -0.5*kPiBy2 ; 668 ddx.d[1] = -0.5*kPiBy2Tail1; 669 FESETENVD(fpenv); 670 return (ddx.f); 671 } 672 else { // numerator positive 673 ddx.d[0] = 0.5*kPiBy2 ; 674 ddx.d[1] = 0.5*kPiBy2Tail1; 675 FESETENVD(fpenv); 676 return (ddx.f); 677 } 678 } 679 else { // denominator negative 680 if (signy) { // numerator negative 681 ddx.d[0] = -k3PiBy4 ; 682 ddx.d[1] = -k3PiBy4Tail1; 683 FESETENVD(fpenv); 684 return (ddx.f); 685 } 686 else { // numerator positive 687 ddx.d[0] = k3PiBy4 ; 688 ddx.d[1] = k3PiBy4Tail1; 689 FESETENVD(fpenv); 690 return (ddx.f); 691 } 692 } 693 } 694 else { // y is Infinite , x is finite 695 if (signy == 0.0) { 696 if (signx == 0.0) { // first quadrant 697 ddx.d[0] = kPiBy2 ; 698 ddx.d[1] = kPiBy2Tail1m; 699 FESETENVD(fpenv); 700 return (ddx.f); 701 } 702 else { // second quadrant 703 ddx.d[0] = kPiBy2 ; 704 ddx.d[1] = kPiBy2Tail1; 705 FESETENVD(fpenv); 706 return (ddx.f); 707 } 708 } 709 else { // yNum < 0.0 710 if (signx == 0.0) { // fourth quadrant 711 ddx.d[0] = -kPiBy2 ; 712 ddx.d[1] = -kPiBy2Tail1m; 713 FESETENVD(fpenv); 714 return (ddx.f); 715 } 716 717 else { // third quadrant 718 ddx.d[0] = -kPiBy2 ; 719 ddx.d[1] = -kPiBy2Tail1; 720 FESETENVD(fpenv); 721 return (ddx.f); 722 } 723 } 724 } 725 } // [y is infinite or NaN] 726 if (expx == 0x7ffu) { // x is infinite or NaN 727 if (sigx != 0) { // NaN x is returned 728 FESETENVD(fpenv); 729 return (x); 730 } 731 else if (signx) { // x is -INF 732 if (signy == 0) { 733 ddx.d[0] = 2.0*kPiBy2 ; 734 ddx.d[1] = 2.0*kPiBy2Tail1m; 735 FESETENVD(fpenv); 736 return (ddx.f); 737 } 738 else { 739 ddx.d[0] = -2.0*kPiBy2 ; 740 ddx.d[1] = -2.0*kPiBy2Tail1m; 741 FESETENVD(fpenv); 742 return (ddx.f); 743 } 744 } 745 else // x is +INF 746 if (signy == 0) { 747 ddx.d[0] = 0.0 ; 748 ddx.d[1] = 0.0; 749 FESETENVD(fpenv); 750 return (ddx.f); 751 } 752 else { 753 ddx.d[0] = -0.0 ; 754 ddx.d[1] = -0.0; 755 FESETENVD(fpenv); 756 return (ddx.f); 757 } 758 } // x is infinite or NaN 759 if ((sigx | expx) == 0u) { // x is zero 760 if ((sigy | expy) == 0u) { // y is zero 761 if (signx) { 762 if (signy) { 763 ddx.d[0] = -2.0*kPiBy2 ; 764 ddx.d[1] = -2.0*kPiBy2Tail1m; 765 FESETENVD(fpenv); 766 return (ddx.f); 767 } 768 else { 769 ddx.d[0] = 2.0*kPiBy2 ; 770 ddx.d[1] = 2.0*kPiBy2Tail1m; 771 FESETENVD(fpenv); 772 return (ddx.f); 773 } 774 } 775 else { 776 FESETENVD(fpenv); 777 return (y); 778 } 779 } 780 else if (signy) { // y < 0.0 781 if (signx) { 782 ddx.d[0] = -kPiBy2 ; 783 ddx.d[1] = -kPiBy2Tail1; 784 FESETENVD(fpenv); 785 return (ddx.f); 786 } 787 else { 788 ddx.d[0] = -kPiBy2 ; 789 ddx.d[1] = -kPiBy2Tail1m; 790 FESETENVD(fpenv); 791 return (ddx.f); 792 } 793 } 794 else { // y > 0.0 795 if (signx) { 796 ddx.d[0] = kPiBy2 ; 797 ddx.d[1] = kPiBy2Tail1; 798 FESETENVD(fpenv); 799 return (ddx.f); 800 } 801 else { 802 ddx.d[0] = kPiBy2 ; 803 ddx.d[1] = kPiBy2Tail1m; 804 FESETENVD(fpenv); 805 return (ddx.f); 806 } 807 } 808 } // [x is zero] 809 if ((sigy | expy) == 0u) { // [zero y, nonzero x] 810 if (signx == 0.0) { // denominator positive 811 ddx.d[0] = yNum; // correctly signed zero result 812 ddx.d[1] = 0.0; 813 FESETENVD(fpenv); 814 return (ddx.f); 815 } 816 else { // negative denominator 817 if (signy == 0) { // numerator is 0, 818 ddx.d[0] = kPi ; 819 ddx.d[1] = kPiTail1m; 820 FESETENVD(fpenv); 821 return (ddx.f); 822 } 823 else { // numerator is -0 824 ddx.d[0] = -kPi ; 825 ddx.d[1] = -kPiTail1m; 826 FESETENVD(fpenv); 827 return (ddx.f); 828 } 829 } 830 } // [zero y, nonzero x] 831 // END OF SPECIAL CASES 832 833 // The code below is for finite y/x values, we first calculate the ratio y/x 834 // for tiny values of either x and y, and for other finite values with extra precision 835 // producing xHead, xTail and frac3. These quantities and the sign of the numerator and 836 // the denomitor are used then to produce ArcTan (y,x) 837 838 // Beginning of tiny numerator or denominator 839 840 if((((ddy.i[0]) & 0x7fffffff) < 0x06B00000)|| (((ddx.i[0]) & 0x7fffffff) < 0x06B00000)) { 841 xDen = xDen*kRescale; // For a tiny arguments, 842 xDenTail = xDenTail*kRescale; // rescale all the input 843 yNum = yNum*kRescale; // so that the full length 844 yNumTail = yNumTail*kRescale; // division can procede. 845 r = 1.0/xDen; 846 if (fabs(r) < kTiny) { // rescaling has made numerator 847 if (xDen > 0) { // too large. Result is 848 xHead = 0.0; // zero for positive denominator 849 xTail = 0.0; 850 frac3 = 0.0; 851 } 852 else { // for neg. denominator, 853 xHead = yNum; // send numerator to qatan 854 xTail = 0.0; // result will be subtracted 855 frac3 = 0.0; // from properly signed Pi later 856 } 857 } 858 } 859 // end of tiny numerator or denominator 860 861 r = 1.0/xDen; // start computation of num/den 862 // normal non-special values of x and y 863 fract = __FMUL( yNum, r ); 864 865 // A detailed division (yHead,yTail)/(xHead,xTail) follows 866 frac = __FMADD( r, __FNMSUB( xDen, fract, yNum ), fract ); // fract + (yNum-xDen*fract)*r; // refine h.o. quotient 867 p29 = __FNMSUB( xDen, frac, yNum ); // yNum - xDen*frac; 868 p30 = __FMUL( frac, xDenTail ); // negative term 869 p31 = __FNMSUB( frac, xDenTail, p30 ); // p30 - frac*xDenTail; 870 p32 = p31; 871 p33 = __FSUB( p29, p30 ); 872 p35 = __FADD( p33, yNumTail ); 873 874 if (fabs(fract) == kInfinityu.f) { 875 xHead = fract; 876 xTail = 0.0; 877 frac3 = 0.0; 878 } 879 else if (fabs(fract)< kInfinityu.f) { 880 frac2 = __FMUL( p35, r ); 881 frac2 = __FMADD( r, __FNMSUB( frac2, xDen, p35 ), frac2 ); // frac2 + (p35-frac2*xDen)*r; // mid. quot. word 882 if (fabs(p29) > fabs(p30)) 883 p34 = p29 - p33 - p30 + p32; 884 else 885 p34 = p29 - (p33+p30)+p32; 886 p36 = __FNMSUB( frac2, xDen, p35 ) + __FNMSUB( frac2, xDenTail, p34 ); // p35 - frac2*xDen + p34 - frac2*xDenTail; 887 if (fabs(p33) > fabs(yNumTail)) 888 p37 = p33 - p35 + yNumTail; 889 else 890 p37 = yNumTail - p35 + p33; 891 p38 = p37 + p36; 892 frac3 = p38*r/__FMADD( frac, frac, 1.0 ); // p38*r/(1.0+frac*frac); // Fraction done 893 xHead = frac; // Use ATAN routine to do 894 xTail = frac2; // most of the work 895 } 896 // Below we use the just evaluated values of xHead and xTail 897 // to first evaluate the quantity "ressmall" which add an extra precision 898 // contribution to frac3. Then, xHead, xTail, frac3, ressmall and 899 // the sign of the numerator (signy) and denominator (signx) 900 // are used to evaluate ArcTan2(y,x) 901 902 // finite result 903 904 //*************************************************************************** 905 // This routine breaks the arguments into five ranges: * 906 // Range 1: 0 <= |x| <= .0859375 * 907 // Range 2: .0859375 <= |x| <= 1.015625 * 908 // Range 3: 1.015625 <= |x| < 13 * 909 // Range 4: 13 <= |x| < 2^107 * 910 // Range 5: 2^107 <= |x| <= Infinity * 911 // * 912 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> * 913 // * 914 // In Range 1, a 15th degree polynomial in x^2 is used to evaluate QATAN. * 915 // * 916 // In Range 2 and, * 917 // In Range 3 the accurate table method is used to range-reduce the * 918 // argument to a small value to be used with an interpolating * 919 // polynomial for QATAN. In Ranges 2 and 3, the resultant * 920 // argument is less than 2^-7, so an 8th degree polynomial can * 921 // be used. Range 3 requires additional work to find the * 922 // correct index into the accurate table. * 923 // * 924 // In Range 4, QATAN(x) = Pi/2 - QATAN(1/x). After taking the reciprocal * 925 // of the argument, the quotient is less than 1/13, so that the * 926 // 15th degree polynomial used for Range 1 is used to compute * 927 // QATAN(1/x) * 928 // * 929 // In Range 5, the correctly rounded value differs from Pi/2 by less than * 930 // 1/2 ulp. It is, however, incorrect to let the value become * 931 // correctly rounded, as that correctly rounded value exceeds * 932 // PI/2 and is in the wrong quadrant. Applying the inverse * 933 // function, QTAN, to the correctly rounded value of PI/2 would * 934 // produce a result of the opposite sign to the argument * 935 // originally given to ATAN. * 936 //*************************************************************************** 937 938 939 // THIS CODE ONLY TREATS RANGES 1 TROUGH 5. WE ASSUME THAT xHead and xTail 940 // are such that we are ALWAYS in Range 1-5. 941 942 absx = fabs(xHead); 943 944 // Range 5 945 946 if (absx >= kLimit4) { // Filter out unusual arguments 947 reshi = kPiBy2; // if the second argument is 948 if (signx == 0.0) { // positive, the result is in 949 resbot = kPiBy2Tail1m; // first or fourth quadrant 950 ressmall = 0; // set up appropriate value of 951 if (xHead < 0.0) { // pi/2, truncated 952 reshi = -reshi; 953 resbot = -resbot; 954 } 955 } 956 else { // Otherwise, result is in the 957 reshi = kPiBy2; // second or third quadrant. 958 resbot = kPiBy2Tail1; // set up pi/2, correctly rounded 959 ressmall = kPiBy2Tail2; 960 if (xHead < 0.0) { 961 reshi = -reshi; 962 resbot = -resbot; 963 ressmall = -ressmall; 964 } 965 } 966 } 967 968 // Ranges 1 and 4 (DO NOT USE TABLE) 969 970 rflag = 0; 971 972 // Range 4 973 974 if ((absx >= kLimit3) && (absx < kLimit4) ) { // Range 4 975 rarg = 1.0/xHead; 976 rflag = 1; // indicate large argument 977 p1 = __FNMSUB( xHead, rarg, 1.0 ); // 1.0 - xHead*rarg; // time to complete hi precision 978 p2 = xTail*rarg; // reciprocal of argument, to 979 p3 = p1 - p2; // use as reduced argument. 980 rarg2a = p3*rarg; 981 rarg2 = rarg2a + __FNMSUB( xHead, rarg2a, p3 )*rarg; // rarg2a + (p3 - xHead*rarg2a)*rarg; 982 xHead = rarg; 983 xTail = rarg2; 984 } 985 986 // Ranges 1 and 4 only 987 988 if( (absx < kLimit1) || ((absx >= kLimit3) && (absx < kLimit4) )) { //Code for Range 1 and Range 4 989 temp = 2.0*xHead*xTail; // direct evaluation of series 990 argsq = __FMADD( xHead, xHead, temp ); // xHead*xHead + temp; // compute square of argument 991 argsq2 = __FMADD( xTail, xTail, __FMSUB( xHead, xHead, argsq ) + temp ); // xHead*xHead - argsq + temp + xTail*xTail; 992 sum = atancoeff[14]; 993 sum = __FMADD( argsq, sum, atancoeff[13] ); // atancoeff[13] + argsq*sum; 994 sum = __FMADD( argsq, sum, atancoeff[12] ); // atancoeff[12] + argsq*sum; 995 sum = __FMADD( argsq, sum, atancoeff[11] ); // atancoeff[11] + argsq*sum; 996 sumt = __FMADD( argsq, sum, atancoeff[10] ); // atancoeff[10] + argsq*sum; 997 sum = __FMADD( argsq, sum, atancoeff[9] ); // atancoeff[9] + argsq*sumt; 998 suml = __FMADD( argsq, sumt, atancoeff[9] - sum ); // atancoeff[9] - sum + argsq*sumt; 999 1000 for (i = 8; i >= 1; i--) { 1001 temps = __FMADD( argsq, sum, atancoeff[i] ); // atancoeff[i] + sum*argsq; 1002 /* suml = atancoeff[i] - temps+sum*argsq + (sum*argsq2 + suml*argsq); */ 1003 suml = __FMADD( sum, argsq, atancoeff[i] - temps ) + __FMADD( sum, argsq2, suml*argsq ); 1004 sum=temps; 1005 } 1006 1007 prodlow = __FMADD( suml, argsq, sum*argsq2 ); // suml*argsq + sum*argsq2; // multiply by arg^2 1008 prod = __FMADD( sum, argsq, prodlow ); // sum*argsq + prodlow; 1009 prodlow = __FMSUB( sum, argsq, prod ) + prodlow; // sum*argsq - prod + prodlow; 1010 temp2 = __FMADD( prodlow, xHead, prod*xTail ); // prodlow*xHead + prod*xTail; // multiply by arg 1011 temp = __FMADD( prod, xHead, temp2 ); // prod*xHead + temp2; 1012 temp2 = __FMSUB( prod, xHead, temp ) + temp2; // prod*xHead - temp + temp2; 1013 sum = temp*kRecip; // sum of series --- 1014 remainder = __FNMSUB( sum, atancoeff[0], temp ); // (temp - sum*atancoeff[0]); 1015 partial = __FADD( remainder, temp2 ); 1016 residual = remainder - partial + temp2; 1017 suml = __FMADD( partial, kRecip, (residual*kRecip) );// partial*kRecip + (residual*kRecip); 1018 res = __FADD( xHead, sum ); // except for argument 1019 reslow = (xHead - res + sum); // exact 1020 resmid = __FADD( xTail, suml ); 1021 restiny = xTail - resmid + suml; 1022 p = __FADD( reslow, resmid ); // sum of middle terms 1023 q = reslow - p + resmid; // possible residual 1024 reshi = res + p; 1025 resbot = (res - reshi + p) + (q + restiny); 1026 if (rflag == 1) { // large magnitude argument 1027 if (xHead > 0) { // fetch pi/2 with proper sign 1028 p1 = kPiBy2; 1029 p2 = kPiBy2Tail1; 1030 p2a = kPiBy2Tail2; 1031 } 1032 else { 1033 p1 = -kPiBy2; 1034 p2 = -kPiBy2Tail1; 1035 p2a = -kPiBy2Tail2; 1036 } 1037 p3 = __FSUB( p1, reshi ); // subtract result from pi/2 1038 p4 = p1 - p3 - reshi; 1039 p5 = __FSUB( p2, resbot ); 1040 p6 = p2 - p5 - resbot + p2a; 1041 p7 = __FADD( p4, p5 ); 1042 reshi = p3 + p7; 1043 if (fabs(p4) > fabs(p5)) 1044 p8 = p4 - p7 + p5; 1045 else 1046 p8 = p5 - p7 + p4; 1047 resbot = __FADD( p3 - reshi + p7, (p6+p8-restiny) ); 1048 ressmall = (p3 - reshi + p7) - resbot + (p6 + p8 - restiny); 1049 } 1050 else //if rflag = 0 i.e., Range 1 1051 ressmall = (res - reshi + p) - resbot + (q + restiny); 1052 } 1053 1054 // Ranges 2 and 3 (USE TABLE) 1055 1056 if( (absx >= kLimit1) && (absx < kLimit3) ) { // Code for Range 2 and Range 3 1057 DeN.f = __FMADD( 64.0, absx, kBig ); // 64.0 *absx+kBig; 1058 if (absx > kLimit2) { // for large args, use recip. Range 3 1059 FESETENVD(kBig+1.0); // use trunc mode momentarily 1060 DeN.f = absx + kBig; // determine range of argument 1061 FESETENVD(kBig+1.0); // use trunc mode momentarily 1062 DeN.f = absx + kBig; // determine range of argument 1063 FESETENVD(kBig); // return to round-to-nearest 1064 index = DeN.i[1]; 1065 i = index - 1; 1066 DeN.f = __FMADD( factor[i], absx, kBig+adjust[i] ); // factor[i]*absx+kBig+adjust[i]; 1067 } 1068 index = DeN.i[1]; 1069 if (xHead < 0) { // use abs. value 1070 arg = -xHead; 1071 argl = -xTail; 1072 } 1073 else { 1074 arg = xHead; 1075 argl = xTail; 1076 } 1077 top = __FSUB( arg, atanPtr[(int32_t)index].One ); 1078 top2 = __FADD( top, argl ); 1079 topextra = arg - top - atanPtr[(int32_t)index].One; 1080 top3 = top - top2 + argl + topextra; // reduced numerator 1081 bot = __FMADD( arg, atanPtr[(int32_t)index].One, 1.0 ); // 1.0 + arg*atanPtr[(int32_t)index].One; 1082 /* bot2 = 1.0 - bot + arg*atanPtr[(int32_t)index].One + argl*atanPtr[(int32_t)index].One; */ // denominator 1083 bot2 = __FMADD( argl, atanPtr[(int32_t)index].One, __FMADD( arg, atanPtr[(int32_t)index].One, 1.0 - bot ) ); 1084 r = 1.0/bot; 1085 quot = r*top2; 1086 quot = __FMADD( __FNMSUB( bot, quot, top2 ) , r, quot ); // quot + (top2-bot*quot)*r; 1087 1088 p29 = __FNMSUB( bot, quot, top2 ); //top2 - quot*bot; 1089 p30 = quot*bot2; // negative term 1090 p33 = p29-p30; 1091 p35 = p33 + top3; 1092 quot2 = p35*r; 1093 quot2 = __FMADD( __FNMSUB( quot2, bot, p35 ), r, quot2 ); // quot2 + (p35-quot2*bot)*r; // second fraction wd. 1094 temp = 2.0*quot*quot2; // reduced arg is (quot,quot2) 1095 argsq = __FMADD( quot, quot, temp ); // quot*quot + temp; // compute square of argument 1096 argsq2 = __FMADD( quot2, quot2, __FMSUB( quot, quot, argsq) + temp ); // quot*quot - argsq + temp + quot2*quot2; 1097 sumt = __FMADD( argsq, atancoeff[7], atancoeff[6] );// atancoeff[6] + argsq*atancoeff[7]; 1098 sum = __FMADD( argsq, sumt, atancoeff[5] ); // atancoeff[5] + argsq*sumt; 1099 suml = __FMADD( argsq, sumt, atancoeff[5] - sum ); // atancoeff[5] - sum + argsq*sumt; 1100 1101 for (i = 4; i >= 1; i--) { 1102 temps = __FMADD( sum, argsq, atancoeff[i] ); // atancoeff[i] + sum*argsq; 1103 /* suml = atancoeff[i] - temps + sum*argsq + (sum*argsq2 + suml*argsq); */ 1104 suml = __FMADD( sum, argsq, atancoeff[i] - temps ) + __FMADD( sum, argsq2, suml*argsq ); 1105 sum = temps; 1106 } 1107 1108 prodlow = __FMADD( suml, argsq, sum*argsq2 ); // suml*argsq + sum*argsq2; // mult. by arg^2 1109 prod = __FMADD( sum, argsq, prodlow ); // sum*argsq + prodlow; 1110 prodlow = __FMSUB( sum, argsq, prod ) + prodlow; // sum*argsq - prod + prodlow; 1111 temp2 = __FMADD( prodlow, quot, prod*quot2 ); // prodlow*quot + prod*quot2; // mult. by arg 1112 temp = __FMADD( prod, quot, temp2 ); // prod*quot + temp2; 1113 temp2 = __FMSUB( prod, quot, temp ) + temp2; // prod*quot - temp + temp2; 1114 sum = temp*kRecip; // sum of series --- 1115 remainder = __FNMSUB( sum, atancoeff[0], temp ); // (temp - sum*atancoeff[0]); 1116 partial = __FADD( remainder, temp2 ); 1117 residual = remainder - partial + temp2; 1118 suml = __FMADD( partial, kRecip, (residual*kRecip) ); // partial*kRecip + (residual*kRecip); 1119 res = __FADD( quot, sum ); // except for argument 1120 reslow = (quot - res + sum); // exact 1121 resmid = __FADD( quot2, suml ); 1122 restiny = quot2 - resmid + suml; 1123 p = __FADD( reslow, resmid ); // sum of middle terms 1124 q = reslow - p + resmid; // possible residual 1125 reshi = __FADD( res, p ); 1126 resbot = (res - reshi + p) + (q + restiny); 1127 result = __FADD( atanPtr[(int32_t)index].Two, reshi ); 1128 reslow = __FADD( atanPtr[(int32_t)index].Three, resbot ); 1129 resmid = atanPtr[(int32_t)index].Two - result + reshi; 1130 restiny = resbot - reslow + atanPtr[(int32_t)index].Three; 1131 restemp = __FADD( resmid, reslow ); 1132 reshi = __FADD( result, restemp ); 1133 1134 if (fabs(resmid) > fabs(reslow)) 1135 restiny = resmid - restemp + reslow + restiny; 1136 else 1137 restiny = reslow - restemp + resmid + restiny; 1138 resbot = result - reshi + restemp + restiny; 1139 if (xHead < 0.0) { 1140 reshi = -reshi; 1141 resbot = -resbot; 1142 result = -result; 1143 restemp = -restemp; 1144 restiny = -restiny; 1145 } 1146 ressmall = (result - reshi + restemp) - resbot + restiny; 1147 } 1148 extra = ressmall + frac3; 1149 if (signx == 0) { // For Positive denominator 1150 ddx.d[0] = __FADD( reshi, (resbot + extra) ); 1151 ddx.d[1] = (reshi - ddx.d[0]) + (resbot + extra); 1152 } 1153 else { 1154 if (signy == 0) { // For Negative denominator 1155 pin = kPi; // return 2nd|3rd quadrand angle, 1156 pin2 = kPiTail1; // depending on sign of numerator 1157 pin3 = kPiTail2; 1158 } 1159 else { 1160 pin = -kPi; // --> Pi+atan, for dnum < 0, 1161 pin2 = -kPiTail1; // atan-Pi, for dnum > 0 1162 pin3 = -kPiTail2; 1163 } 1164 restop = __FADD( pin, reshi ); 1165 resmid = pin - restop + reshi; 1166 reslow = __FADD( pin2, resbot ); 1167 restiny = pin2 - reslow + resbot + extra; 1168 resint = __FADD( resmid, reslow ); 1169 reshi = __FADD( restop, resint ); 1170 resbot = restop - reshi+resint; 1171 if (fabs(resmid) > fabs(reslow)) 1172 resbot = resbot + (resmid-resint+reslow+restiny); 1173 else 1174 resbot = resbot + (reslow-resint+resmid+restiny); 1175 ddx.d[0] = __FADD( reshi, resbot ); 1176 ddx.d[1] = (reshi - ddx.d[0]) + resbot; 1177 } 1178 1179 FESETENVD(fpenv); 1180 return (ddx.f); 1181} 1182#endif 1183