Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

393 lines
8.9 KiB

  1. //-----------------------------------------------------------------------------
  2. // Package Title ratpak
  3. // File itrans.c
  4. // Author Timothy David Corrie Jr. ([email protected])
  5. // Copyright (C) 1995-96 Microsoft
  6. // Date 01-16-95
  7. //
  8. //
  9. // Description
  10. //
  11. // Contains inverse sin, cos, tan functions for rationals
  12. //
  13. // Special Information
  14. //
  15. //-----------------------------------------------------------------------------
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #if defined( DOS )
  20. #include <dosstub.h>
  21. #else
  22. #include <windows.h>
  23. #endif
  24. #include <ratpak.h>
  25. void ascalerat( IN OUT PRAT *pa, IN ANGLE_TYPE angletype )
  26. {
  27. switch ( angletype )
  28. {
  29. case ANGLE_RAD:
  30. break;
  31. case ANGLE_DEG:
  32. divrat( pa, two_pi );
  33. mulrat( pa, rat_360 );
  34. break;
  35. case ANGLE_GRAD:
  36. divrat( pa, two_pi );
  37. mulrat( pa, rat_400 );
  38. break;
  39. }
  40. }
  41. //-----------------------------------------------------------------------------
  42. //
  43. // FUNCTION: asinrat, _asinrat
  44. //
  45. // ARGUMENTS: x PRAT representation of number to take the inverse
  46. // sine of
  47. // RETURN: asin of x in PRAT form.
  48. //
  49. // EXPLANATION: This uses Taylor series
  50. //
  51. // n
  52. // ___ 2 2
  53. // \ ] (2j+1) X
  54. // \ thisterm ; where thisterm = thisterm * ---------
  55. // / j j+1 j (2j+2)*(2j+3)
  56. // /__]
  57. // j=0
  58. //
  59. // thisterm = X ; and stop when thisterm < precision used.
  60. // 0 n
  61. //
  62. // If abs(x) > 0.85 then an alternate form is used
  63. // pi/2-sgn(x)*asin(sqrt(1-x^2)
  64. //
  65. //
  66. //-----------------------------------------------------------------------------
  67. void _asinrat( PRAT *px )
  68. {
  69. CREATETAYLOR();
  70. DUPRAT(pret,*px);
  71. DUPRAT(thisterm,*px);
  72. DUPNUM(n2,num_one);
  73. do
  74. {
  75. NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
  76. INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2));
  77. }
  78. while ( !SMALL_ENOUGH_RAT( thisterm ) );
  79. DESTROYTAYLOR();
  80. }
  81. void asinanglerat( IN OUT PRAT *pa, IN ANGLE_TYPE angletype )
  82. {
  83. asinrat( pa );
  84. ascalerat( pa, angletype );
  85. }
  86. void asinrat( PRAT *px )
  87. {
  88. long sgn;
  89. PRAT pret=NULL;
  90. PRAT phack=NULL;
  91. sgn = (*px)->pp->sign* (*px)->pq->sign;
  92. (*px)->pp->sign = 1;
  93. (*px)->pq->sign = 1;
  94. // Nasty hack to avoid the really bad part of the asin curve near +/-1.
  95. DUPRAT(phack,*px);
  96. subrat(&phack,rat_one);
  97. // Since *px might be epsilon near zero we must set it to zero.
  98. if ( rat_le(phack,rat_smallest) && rat_ge(phack,rat_negsmallest) )
  99. {
  100. destroyrat(phack);
  101. DUPRAT( *px, pi_over_two );
  102. }
  103. else
  104. {
  105. destroyrat(phack);
  106. if ( rat_gt( *px, pt_eight_five ) )
  107. {
  108. if ( rat_gt( *px, rat_one ) )
  109. {
  110. subrat( px, rat_one );
  111. if ( rat_gt( *px, rat_smallest ) )
  112. {
  113. throw( CALC_E_DOMAIN );
  114. }
  115. else
  116. {
  117. DUPRAT(*px,rat_one);
  118. }
  119. }
  120. DUPRAT(pret,*px);
  121. mulrat( px, pret );
  122. (*px)->pp->sign *= -1;
  123. addrat( px, rat_one );
  124. rootrat( px, rat_two );
  125. _asinrat( px );
  126. (*px)->pp->sign *= -1;
  127. addrat( px, pi_over_two );
  128. destroyrat(pret);
  129. }
  130. else
  131. {
  132. _asinrat( px );
  133. }
  134. }
  135. (*px)->pp->sign = sgn;
  136. (*px)->pq->sign = 1;
  137. }
  138. //-----------------------------------------------------------------------------
  139. //
  140. // FUNCTION: acosrat, _acosrat
  141. //
  142. // ARGUMENTS: x PRAT representation of number to take the inverse
  143. // cosine of
  144. // RETURN: acos of x in PRAT form.
  145. //
  146. // EXPLANATION: This uses Taylor series
  147. //
  148. // n
  149. // ___ 2 2
  150. // \ ] (2j+1) X
  151. // \ thisterm ; where thisterm = thisterm * ---------
  152. // / j j+1 j (2j+2)*(2j+3)
  153. // /__]
  154. // j=0
  155. //
  156. // thisterm = 1 ; and stop when thisterm < precision used.
  157. // 0 n
  158. //
  159. // In this case pi/2-asin(x) is used. At least for now _acosrat isn't
  160. // called.
  161. //
  162. //-----------------------------------------------------------------------------
  163. void acosanglerat( IN OUT PRAT *pa, IN ANGLE_TYPE angletype )
  164. {
  165. acosrat( pa );
  166. ascalerat( pa, angletype );
  167. }
  168. void _acosrat( PRAT *px )
  169. {
  170. CREATETAYLOR();
  171. createrat(thisterm);
  172. thisterm->pp=longtonum( 1L, BASEX );
  173. thisterm->pq=longtonum( 1L, BASEX );
  174. DUPNUM(n2,num_one);
  175. do
  176. {
  177. NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
  178. INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2));
  179. }
  180. while ( !SMALL_ENOUGH_RAT( thisterm ) );
  181. DESTROYTAYLOR();
  182. }
  183. void acosrat( PRAT *px )
  184. {
  185. long sgn;
  186. sgn = (*px)->pp->sign*(*px)->pq->sign;
  187. (*px)->pp->sign = 1;
  188. (*px)->pq->sign = 1;
  189. if ( rat_equ( *px, rat_one ) )
  190. {
  191. if ( sgn == -1 )
  192. {
  193. DUPRAT(*px,pi);
  194. }
  195. else
  196. {
  197. DUPRAT( *px, rat_zero );
  198. }
  199. }
  200. else
  201. {
  202. (*px)->pp->sign = sgn;
  203. asinrat( px );
  204. (*px)->pp->sign *= -1;
  205. addrat(px,pi_over_two);
  206. }
  207. }
  208. //-----------------------------------------------------------------------------
  209. //
  210. // FUNCTION: atanrat, _atanrat
  211. //
  212. // ARGUMENTS: x PRAT representation of number to take the inverse
  213. // hyperbolic tangent of
  214. //
  215. // RETURN: atanh of x in PRAT form.
  216. //
  217. // EXPLANATION: This uses Taylor series
  218. //
  219. // n
  220. // ___ 2
  221. // \ ] (2j)*X (-1^j)
  222. // \ thisterm ; where thisterm = thisterm * ---------
  223. // / j j+1 j (2j+2)
  224. // /__]
  225. // j=0
  226. //
  227. // thisterm = X ; and stop when thisterm < precision used.
  228. // 0 n
  229. //
  230. // If abs(x) > 0.85 then an alternate form is used
  231. // asin(x/sqrt(q+x^2))
  232. //
  233. // And if abs(x) > 2.0 then this form is used.
  234. //
  235. // pi/2 - atan(1/x)
  236. //
  237. //-----------------------------------------------------------------------------
  238. void atananglerat( IN OUT PRAT *pa, IN ANGLE_TYPE angletype )
  239. {
  240. atanrat( pa );
  241. ascalerat( pa, angletype );
  242. }
  243. void _atanrat( PRAT *px )
  244. {
  245. CREATETAYLOR();
  246. DUPRAT(pret,*px);
  247. DUPRAT(thisterm,*px);
  248. DUPNUM(n2,num_one);
  249. xx->pp->sign *= -1;
  250. do {
  251. NEXTTERM(xx,MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2));
  252. } while ( !SMALL_ENOUGH_RAT( thisterm ) );
  253. DESTROYTAYLOR();
  254. }
  255. void atan2rat( PRAT *py, PRAT x )
  256. {
  257. if ( rat_gt( x, rat_zero ) )
  258. {
  259. if ( !zerrat( (*py) ) )
  260. {
  261. divrat( py, x);
  262. atanrat( py );
  263. }
  264. }
  265. else if ( rat_lt( x, rat_zero ) )
  266. {
  267. if ( rat_gt( (*py), rat_zero ) )
  268. {
  269. divrat( py, x);
  270. atanrat( py );
  271. addrat( py, pi );
  272. }
  273. else if ( rat_lt( (*py), rat_zero ) )
  274. {
  275. divrat( py, x);
  276. atanrat( py );
  277. subrat( py, pi );
  278. }
  279. else // (*py) == 0
  280. {
  281. DUPRAT( *py, pi );
  282. }
  283. }
  284. else // x == 0
  285. {
  286. if ( !zerrat( (*py) ) )
  287. {
  288. int sign;
  289. sign=(*py)->pp->sign*(*py)->pq->sign;
  290. DUPRAT( *py, pi_over_two );
  291. (*py)->pp->sign = sign;
  292. }
  293. else // (*py) == 0
  294. {
  295. DUPRAT( *py, rat_zero );
  296. }
  297. }
  298. }
  299. void atanrat( PRAT *px )
  300. {
  301. long sgn;
  302. PRAT tmpx=NULL;
  303. sgn = (*px)->pp->sign * (*px)->pq->sign;
  304. (*px)->pp->sign = 1;
  305. (*px)->pq->sign = 1;
  306. if ( rat_gt( (*px), pt_eight_five ) )
  307. {
  308. if ( rat_gt( (*px), rat_two ) )
  309. {
  310. (*px)->pp->sign = sgn;
  311. (*px)->pq->sign = 1;
  312. DUPRAT(tmpx,rat_one);
  313. divrat(&tmpx,(*px));
  314. _atanrat(&tmpx);
  315. tmpx->pp->sign = sgn;
  316. tmpx->pq->sign = 1;
  317. DUPRAT(*px,pi_over_two);
  318. subrat(px,tmpx);
  319. destroyrat( tmpx );
  320. }
  321. else
  322. {
  323. (*px)->pp->sign = sgn;
  324. DUPRAT(tmpx,*px);
  325. mulrat( &tmpx, *px );
  326. addrat( &tmpx, rat_one );
  327. rootrat( &tmpx, rat_two );
  328. divrat( px, tmpx );
  329. destroyrat( tmpx );
  330. asinrat( px );
  331. (*px)->pp->sign = sgn;
  332. (*px)->pq->sign = 1;
  333. }
  334. }
  335. else
  336. {
  337. (*px)->pp->sign = sgn;
  338. (*px)->pq->sign = 1;
  339. _atanrat( px );
  340. }
  341. if ( rat_gt( *px, pi_over_two ) )
  342. {
  343. subrat( px, pi );
  344. }
  345. }