trigarcf.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. /*++
  2. Copyright (c) 2017 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. trigarcf.c
  9. Abstract:
  10. This module implements support for the inverse trigonometric functions:
  11. arc sine arc cosine, and arc tangent.
  12. Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  13. Developed at SunPro, a Sun Microsystems, Inc. business.
  14. Permission to use, copy, modify, and distribute this
  15. software is freely granted, provided that this notice
  16. is preserved.
  17. Author:
  18. Chris Stevens 5-Jan-2017
  19. Environment:
  20. User Mode C Library
  21. --*/
  22. //
  23. // ------------------------------------------------------------------- Includes
  24. //
  25. #include "../libcp.h"
  26. #include "mathp.h"
  27. //
  28. // ---------------------------------------------------------------- Definitions
  29. //
  30. #define ARC_SINE_FLOAT_LOW_THRESHOLD_WORD 0x32000000
  31. #define ARC_SINE_FLOAT_UPPER_APPROXIMATION_WORD 0x3F79999A
  32. #define ARC_COSINE_FLOAT_LOW_THRESHOLD_WORD 0x32800000
  33. #define ARC_TANGENT_FLOAT_HIGH_THRESHOLD_WORD 0x4C800000
  34. #define ARC_TANGENT_FLOAT_LOW_THRESHOLD_WORD 0x3EE00000
  35. #define ARC_TANGENT_FLOAT_ZERO_THRESHOLD_WORD 0x39800000
  36. #define ARC_TANGENT_FLOAT_MIDDLE_THRESHOLD_WORD 0x3F980000
  37. #define ARC_TANGENT_FLOAT_MIDDLE_LOW_THRESHOLD_WORD 0x3F300000
  38. #define ARC_TANGENT_FLOAT_MIDDLE_HIGH_THRESHOLD_WORD 0x401C0000
  39. //
  40. // ------------------------------------------------------ Data Type Definitions
  41. //
  42. //
  43. // ----------------------------------------------- Internal Function Prototypes
  44. //
  45. //
  46. // -------------------------------------------------------------------- Globals
  47. //
  48. const float ClFloatPiLow = -8.7422776573e-08;
  49. const float ClFloatPiOver2High = 1.5707962513e+00;
  50. const float ClFloatPiOver2Low = 7.5497894159e-08;
  51. const float ClFloatPiOver4High = 7.8539816339e-01;
  52. //
  53. // Define the coefficients used the in the R(x^2) calculation used for arc sine.
  54. //
  55. const float ClArcSineFloatNumerator0 = 1.666675248e-01;
  56. const float ClArcSineFloatNumerator1 = 7.495297643e-02;
  57. const float ClArcSineFloatNumerator2 = 4.547037598e-02;
  58. const float ClArcSineFloatNumerator3 = 2.417951451e-02;
  59. const float ClArcSineFloatNumerator4 = 4.216630880e-02;
  60. //
  61. // Define the coefficients used the in the R(x^2) calculation used for arc
  62. // cosine.
  63. //
  64. const float ClArcCosineFloatNumerator0 = 1.6666586697e-01;
  65. const float ClArcCosineFloatNumerator1 = -4.2743422091e-02;
  66. const float ClArcCosineFloatNumerator2 = -8.6563630030e-03;
  67. const float ClArcCosineFloatDenominator1 = -7.0662963390e-01;
  68. //
  69. // Define constants used in the arc tangent computation. The high and low
  70. // arrays store precomputed values for the arc tangent of 0.5, 1.0, 1.5, and
  71. // infinity.
  72. //
  73. const float ClArcTangentFloatHigh[] = {
  74. 4.6364760399e-01,
  75. 7.8539812565e-01,
  76. 9.8279368877e-01,
  77. 1.5707962513e+00,
  78. };
  79. const float ClArcTangentFloatLow[] = {
  80. 5.0121582440e-09,
  81. 3.7748947079e-08,
  82. 3.4473217170e-08,
  83. 7.5497894159e-08,
  84. };
  85. const float ClArcTangentFloat[] = {
  86. 3.3333328366e-01,
  87. -1.9999158382e-01,
  88. 1.4253635705e-01,
  89. -1.0648017377e-01,
  90. 6.1687607318e-02,
  91. };
  92. //
  93. // ------------------------------------------------------------------ Functions
  94. //
  95. LIBC_API
  96. float
  97. asinf (
  98. float Value
  99. )
  100. /*++
  101. Routine Description:
  102. This routine computes the arc sine of the given value.
  103. Arguments:
  104. Value - Supplies the sine value to convert back to an angle.
  105. Return Value:
  106. Returns the arc sine of the value, in radians.
  107. --*/
  108. {
  109. LONG AbsoluteWord;
  110. float ArcSine;
  111. float Correction;
  112. float Denominator;
  113. float HalfFlipped;
  114. float Numerator;
  115. float Root;
  116. float RootHigh;
  117. float Value2;
  118. FLOAT_PARTS ValueParts;
  119. LONG Word;
  120. ValueParts.Float = Value;
  121. Word = ValueParts.Ulong;
  122. AbsoluteWord = Word & ~FLOAT_SIGN_BIT;
  123. //
  124. // Handle the absolute value being greater than or equal to one.
  125. //
  126. if (AbsoluteWord >= FLOAT_ONE_WORD) {
  127. //
  128. // asin(1) = +-pi/2 with inexact.
  129. //
  130. if (AbsoluteWord == FLOAT_ONE_WORD) {
  131. return Value * ClFloatPiOver2High + Value * ClFloatPiOver2Low;
  132. }
  133. //
  134. // asin of a value greater than 1 is NaN.
  135. //
  136. return (Value - Value) / (Value - Value);
  137. //
  138. // Work it out if the absolute value is less than 0.5.
  139. //
  140. } else if (AbsoluteWord < FLOAT_ONE_HALF_WORD) {
  141. if (AbsoluteWord < ARC_SINE_FLOAT_LOW_THRESHOLD_WORD) {
  142. if (ClFloatHugeValue + Value > ClFloatOne) {
  143. //
  144. // Return the value with inexact if the value is not zero.
  145. //
  146. return Value;
  147. }
  148. }
  149. Value2 = Value * Value;
  150. Numerator = Value2 *
  151. (ClArcSineFloatNumerator0 + Value2 *
  152. (ClArcSineFloatNumerator1 + Value2 *
  153. (ClArcSineFloatNumerator2 + Value2 *
  154. (ClArcSineFloatNumerator3 + Value2 *
  155. ClArcSineFloatNumerator4))));
  156. return Value + Value * Numerator;
  157. }
  158. //
  159. // The absolute value must be less than one and greater than or equal to
  160. // 0.5.
  161. //
  162. HalfFlipped = ClFloatOne - fabsf(Value);
  163. HalfFlipped = HalfFlipped * ClFloatOneHalf;
  164. Numerator = HalfFlipped *
  165. (ClArcSineFloatNumerator0 + HalfFlipped *
  166. (ClArcSineFloatNumerator1 + HalfFlipped *
  167. (ClArcSineFloatNumerator2 + HalfFlipped *
  168. (ClArcSineFloatNumerator3 + HalfFlipped *
  169. ClArcSineFloatNumerator4))));
  170. Root = sqrtf(HalfFlipped);
  171. //
  172. // Use the easier evaluation if the absolute value is greater than about
  173. // 0.975.
  174. //
  175. if (AbsoluteWord >= ARC_SINE_FLOAT_UPPER_APPROXIMATION_WORD) {
  176. ArcSine = ClFloatPiOver2High -
  177. ((float)2.0 * (Root + Root * Numerator) - ClFloatPiOver2Low);
  178. } else {
  179. ValueParts.Float = Root;
  180. ValueParts.Ulong &= FLOAT_TRUNCATE_VALUE_MASK;
  181. RootHigh = ValueParts.Float;
  182. Correction = (HalfFlipped - RootHigh * RootHigh) / (Root + RootHigh);
  183. Numerator = (float)2.0 * Root * Numerator -
  184. (ClFloatPiOver2Low - (float)2.0 * Correction);
  185. Denominator = ClFloatPiOver4High - (float)2.0 * RootHigh;
  186. ArcSine = ClFloatPiOver4High - (Numerator - Denominator);
  187. }
  188. if (Word > 0) {
  189. return ArcSine;
  190. }
  191. return -ArcSine;
  192. }
  193. LIBC_API
  194. float
  195. acosf (
  196. float Value
  197. )
  198. /*++
  199. Routine Description:
  200. This routine computes the arc cosine of the given value.
  201. Arguments:
  202. Value - Supplies the cosine value to convert back to an angle.
  203. Return Value:
  204. Returns the arc cosine of the value, in radians.
  205. --*/
  206. {
  207. LONG AbsoluteWord;
  208. float Approximation;
  209. float ArcCosine;
  210. float Correction;
  211. float Denominator;
  212. float Input;
  213. float Numerator;
  214. float Quotient;
  215. float Root;
  216. float RootHigh;
  217. FLOAT_PARTS ValueParts;
  218. LONG Word;
  219. ValueParts.Float = Value;
  220. Word = ValueParts.Ulong;
  221. AbsoluteWord = Word & ~FLOAT_SIGN_BIT;
  222. //
  223. // Check if the value is greater than or equal to one.
  224. //
  225. if (AbsoluteWord >= FLOAT_ONE_WORD) {
  226. //
  227. // Check if the absolute value equals one exactly.
  228. //
  229. if (AbsoluteWord == FLOAT_ONE_WORD) {
  230. //
  231. // The arc cosine of 1 is zero.
  232. //
  233. if (Word > 0) {
  234. return 0.0;
  235. }
  236. //
  237. // The arc cosine of -1 is pi.
  238. //
  239. return ClFloatPi + (float)2.0 * ClFloatPiOver2Low;
  240. }
  241. //
  242. // The arc cosine of something with an absolute value greater than one
  243. // is NaN.
  244. //
  245. return (Value - Value) / (Value - Value);
  246. }
  247. //
  248. // Handle an absolute value less than 0.5.
  249. //
  250. if (AbsoluteWord < FLOAT_ONE_HALF_WORD) {
  251. //
  252. // Really small values are just pi/2.
  253. //
  254. if (AbsoluteWord <= ARC_COSINE_FLOAT_LOW_THRESHOLD_WORD) {
  255. return ClFloatPiOver2High + ClFloatPiOver2Low;
  256. }
  257. Input = Value * Value;
  258. Numerator = Input *
  259. (ClArcCosineFloatNumerator0 + Input *
  260. (ClArcCosineFloatNumerator1 + Input *
  261. ClArcCosineFloatNumerator2));
  262. Denominator = ClFloatOne + Input * ClArcCosineFloatDenominator1;
  263. Quotient = Numerator / Denominator;
  264. ArcCosine = ClFloatPiOver2High -
  265. (Value - (ClFloatPiOver2Low - Value * Quotient));
  266. return ArcCosine;
  267. //
  268. // Handle the value being less than -0.5.
  269. //
  270. } else if (Word < 0) {
  271. Input = (ClFloatOne + Value) * (float)0.5;
  272. Numerator = Input *
  273. (ClArcCosineFloatNumerator0 + Input *
  274. (ClArcCosineFloatNumerator1 + Input *
  275. ClArcCosineFloatNumerator2));
  276. Denominator = ClFloatOne + Input * ClArcCosineFloatDenominator1;
  277. Root = sqrtf(Input);
  278. Quotient = Numerator / Denominator;
  279. Approximation = Quotient * Root - ClFloatPiOver2Low;
  280. return ClFloatPi - (float)2.0 * (Root + Approximation);
  281. }
  282. //
  283. // The value is greater than 0.5.
  284. //
  285. Input = (ClFloatOne - Value) * (float)0.5;
  286. Root = sqrtf(Input);
  287. ValueParts.Float = Root;
  288. ValueParts.Ulong &= FLOAT_TRUNCATE_VALUE_MASK;
  289. RootHigh = ValueParts.Float;
  290. Correction = (Input - RootHigh * RootHigh) / (Root + RootHigh);
  291. Numerator = Input *
  292. (ClArcCosineFloatNumerator0 + Input *
  293. (ClArcCosineFloatNumerator1 + Input *
  294. ClArcCosineFloatNumerator2));
  295. Denominator = ClFloatOne + Input * ClArcCosineFloatDenominator1;
  296. Quotient = Numerator / Denominator;
  297. Approximation = Quotient * Root + Correction;
  298. return (float)2.0 * (RootHigh + Approximation);
  299. }
  300. LIBC_API
  301. float
  302. atanf (
  303. float Value
  304. )
  305. /*++
  306. Routine Description:
  307. This routine computes the arc tangent of the given value.
  308. Arguments:
  309. Value - Supplies the tangent value to convert back to an angle.
  310. Return Value:
  311. Returns the arc tangent of the value, in radians.
  312. --*/
  313. {
  314. LONG AbsoluteWord;
  315. float ArcTangent;
  316. float Evens;
  317. float Odds;
  318. float Value2;
  319. float Value4;
  320. FLOAT_PARTS ValueParts;
  321. LONG Word;
  322. LONG Zone;
  323. ValueParts.Float = Value;
  324. Word = ValueParts.Ulong;
  325. AbsoluteWord = Word & ~FLOAT_SIGN_BIT;
  326. if (AbsoluteWord >= ARC_TANGENT_FLOAT_HIGH_THRESHOLD_WORD) {
  327. //
  328. // Handle infinity and NaN.
  329. //
  330. if (AbsoluteWord > FLOAT_NAN) {
  331. return Value + Value;
  332. }
  333. if (Word > 0) {
  334. ArcTangent = ClArcTangentFloatHigh[3] +
  335. *(volatile float *)&ClArcTangentFloatLow[3];
  336. return ArcTangent;
  337. }
  338. ArcTangent = -ClArcTangentFloatHigh[3] -
  339. *(volatile float *)&ClArcTangentFloatLow[3];
  340. return ArcTangent;
  341. }
  342. //
  343. // Handle the value in its smallest range.
  344. //
  345. if (AbsoluteWord < ARC_TANGENT_FLOAT_LOW_THRESHOLD_WORD) {
  346. //
  347. // Handle the value being basically zero.
  348. //
  349. if (AbsoluteWord < ARC_TANGENT_FLOAT_ZERO_THRESHOLD_WORD) {
  350. if (ClFloatHugeValue + Value > ClFloatOne) {
  351. //
  352. // Raise an inexact condition.
  353. //
  354. return Value;
  355. }
  356. }
  357. Zone = -1;
  358. } else {
  359. Value = fabsf(Value);
  360. if (AbsoluteWord < ARC_TANGENT_FLOAT_MIDDLE_THRESHOLD_WORD) {
  361. if (AbsoluteWord < ARC_TANGENT_FLOAT_MIDDLE_LOW_THRESHOLD_WORD) {
  362. Zone = 0;
  363. Value = ((float)2.0 * Value - ClFloatOne) /
  364. ((float)2.0 + Value);
  365. } else {
  366. Zone = 1;
  367. Value = (Value - ClFloatOne) / (Value + ClFloatOne);
  368. }
  369. } else {
  370. if (AbsoluteWord < ARC_TANGENT_FLOAT_MIDDLE_HIGH_THRESHOLD_WORD) {
  371. Zone = 2;
  372. Value = (Value - (float)1.5) /
  373. (ClFloatOne + (float)1.5 * Value);
  374. } else {
  375. Zone = 3;
  376. Value = -(float)1.0 / Value;
  377. }
  378. }
  379. }
  380. Value2 = Value * Value;
  381. Value4 = Value2 * Value2;
  382. //
  383. // Calculate the big polynomial in two chunks, the even coefficients and
  384. // the odd ones.
  385. //
  386. Evens = Value2 *
  387. (ClArcTangentFloat[0] + Value4 *
  388. (ClArcTangentFloat[2] + Value4 * ClArcTangentFloat[4]));
  389. Odds = Value4 * (ClArcTangentFloat[1] + Value4 * ClArcTangentFloat[3]);
  390. if (Zone < 0) {
  391. return Value - Value * (Evens + Odds);
  392. }
  393. ArcTangent = ClArcTangentFloatHigh[Zone] -
  394. ((Value * (Evens + Odds) - ClArcTangentFloatLow[Zone]) -
  395. Value);
  396. if (Word < 0) {
  397. return -ArcTangent;
  398. }
  399. return ArcTangent;
  400. }
  401. LIBC_API
  402. float
  403. atan2f (
  404. float Numerator,
  405. float Denominator
  406. )
  407. /*++
  408. Routine Description:
  409. This routine computes the arc tangent of the given values, using the signs
  410. of both the numerator and the denominator to determine the correct
  411. quadrant for the output angle.
  412. Arguments:
  413. Numerator - Supplies the numerator to the tangent value.
  414. Denominator - Supplies the denominator to the tangent value.
  415. Return Value:
  416. Returns the arc tangent of the value, in radians.
  417. Pi if the numerator is +/- 0 and the denominator is negative.
  418. +/- 0 if the numerator is +/- 0 and the denominator is positive.
  419. Negative pi over 2 if the numerator is negative and the denominator is
  420. +/- 0.
  421. Pi over 2 if the numerator is positive and the denominator is +/- 0.
  422. NaN if either input is NaN.
  423. Returns the numerator over the denominator if the result underflows.
  424. +/- Pi if the numerator is +/- 0 and the denominator is -0.
  425. +/- 0 if the numerator is +/- 0 and the denominator is +0.
  426. +/- Pi for positive finite values of the numerator and -Infinity in the
  427. denominator.
  428. +/- 0 for positive finite values of the numerator and +Infinity in the
  429. denominator.
  430. +/- Pi/2 for finite values of the denominator if the numerator is
  431. +/- Infinity.
  432. +/- 3Pi/4 if the numerator is +/- Infinity and the denominator is -Infinity.
  433. +/- Pi/4 if the numerator is +/- Infinity and the denominator is +Infinity.
  434. --*/
  435. {
  436. LONG AbsoluteDenominator;
  437. LONG AbsoluteNumerator;
  438. float ArcTangent;
  439. LONG DenominatorWord;
  440. FLOAT_PARTS DenominatorParts;
  441. LONG NumeratorWord;
  442. FLOAT_PARTS NumeratorParts;
  443. LONG QuotientHigh;
  444. LONG Signs;
  445. DenominatorParts.Float = Denominator;
  446. DenominatorWord = DenominatorParts.Ulong;
  447. AbsoluteDenominator = DenominatorWord & ~FLOAT_SIGN_BIT;
  448. NumeratorParts.Float = Numerator;
  449. NumeratorWord = NumeratorParts.Ulong;
  450. AbsoluteNumerator = NumeratorWord & ~FLOAT_SIGN_BIT;
  451. //
  452. // Check to see if the denominator or numerator is NaN.
  453. //
  454. if ((AbsoluteDenominator > FLOAT_NAN) || (AbsoluteNumerator > FLOAT_NAN)) {
  455. return Denominator + Numerator;
  456. }
  457. //
  458. // If the denominator is one, just return the arc tangent of the numerator.
  459. //
  460. if (DenominatorWord == FLOAT_ONE_WORD) {
  461. return atanf(Numerator);
  462. }
  463. //
  464. // Switch based on the signs.
  465. //
  466. Signs = ((NumeratorWord >> FLOAT_SIGN_BIT_SHIFT) & 0x1) |
  467. ((DenominatorWord >> (FLOAT_SIGN_BIT_SHIFT - 1)) & 0x2);
  468. //
  469. // Handle the case when the numerator is zero.
  470. //
  471. if (AbsoluteNumerator == 0) {
  472. switch (Signs) {
  473. //
  474. // The arc tangent of +-0 / +anything is +-0.
  475. //
  476. case 0:
  477. case 1:
  478. return Numerator;
  479. //
  480. // The arc tangent of +0 / -anything is pi.
  481. //
  482. case 2:
  483. return ClFloatPi + ClFloatTinyValue;
  484. //
  485. // The arc tangent of -0 / -anything is -pi.
  486. //
  487. case 3:
  488. return -ClFloatPi - ClFloatTinyValue;
  489. }
  490. }
  491. //
  492. // Handle the denominator being zero.
  493. //
  494. if (AbsoluteDenominator == 0) {
  495. if (NumeratorWord < 0) {
  496. return -ClFloatPiOver2High - ClFloatTinyValue;
  497. } else {
  498. return ClFloatPiOver2High + ClFloatTinyValue;
  499. }
  500. }
  501. //
  502. // Handle the denominator being Infinity.
  503. //
  504. if (AbsoluteDenominator == FLOAT_NAN) {
  505. if (AbsoluteNumerator == FLOAT_NAN) {
  506. switch (Signs) {
  507. //
  508. // The arc tangent of +Infinity / +Infinity is pi/4.
  509. //
  510. case 0:
  511. return ClFloatPiOver4High + ClFloatTinyValue;
  512. //
  513. // The arc tangent of -Infinity / +Infinity is -pi/4.
  514. //
  515. case 1:
  516. return -ClFloatPiOver4High - ClFloatTinyValue;
  517. //
  518. // The arc tangent of +Infinity / -Infinity is 3pi/4.
  519. //
  520. case 2:
  521. return (float)3.0 * ClFloatPiOver4High + ClFloatTinyValue;
  522. //
  523. // The arc tangent of -Infinity / -Infinity is -3pi/4.
  524. //
  525. case 3:
  526. return (float)-3.0 * ClFloatPiOver4High - ClFloatTinyValue;
  527. }
  528. } else {
  529. switch (Signs) {
  530. //
  531. // The arc tangent of +anything / +Infinity is 0.
  532. //
  533. case 0:
  534. return ClFloatZero;
  535. //
  536. // The arc tangent of -anything / +Infinity is -0.
  537. //
  538. case 1:
  539. return -ClFloatZero;
  540. //
  541. // The arc tangent of +anything / -Infinity is pi.
  542. //
  543. case 2:
  544. return ClFloatPi + ClFloatTinyValue;
  545. //
  546. // The arc tangent of -anything / -Infinity is -pi.
  547. //
  548. case 3:
  549. return -ClFloatPi - ClFloatTinyValue;
  550. }
  551. }
  552. }
  553. //
  554. // Handle the numerator being Infinity.
  555. //
  556. if (AbsoluteNumerator == FLOAT_NAN) {
  557. if (NumeratorWord < 0) {
  558. return -ClFloatPiOver2High - ClFloatTinyValue;
  559. } else {
  560. return ClFloatPiOver2High + ClFloatTinyValue;
  561. }
  562. }
  563. //
  564. // Compute the quotient.
  565. //
  566. QuotientHigh = (AbsoluteNumerator - AbsoluteDenominator) >>
  567. FLOAT_EXPONENT_SHIFT;
  568. //
  569. // Handle |Numerator / Denominator| > 2^26 (unsafe division).
  570. //
  571. if (QuotientHigh > 26) {
  572. ArcTangent = ClFloatPiOver2High + (float)0.5 * ClFloatPiLow;
  573. Signs &= 0x1;
  574. } else if ((DenominatorWord < 0) && (QuotientHigh < -26)) {
  575. ArcTangent = 0.0;
  576. } else {
  577. ArcTangent = atanf(fabsf(Numerator / Denominator));
  578. }
  579. switch (Signs) {
  580. //
  581. // Return the arc tangent of two positive numbers.
  582. //
  583. case 0:
  584. return ArcTangent;
  585. //
  586. // Negate the value for a negative numerator.
  587. //
  588. case 1:
  589. return -ArcTangent;
  590. //
  591. // Return pi minus the result for a negative denominator.
  592. //
  593. case 2:
  594. return ClFloatPi - (ArcTangent - ClFloatPiLow);
  595. //
  596. // Return the result minus pi for a negative numerator and denominator.
  597. //
  598. default:
  599. break;
  600. }
  601. return (ArcTangent - ClFloatPiLow) - ClFloatPi;
  602. }
  603. //
  604. // --------------------------------------------------------- Internal Functions
  605. //