float.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %
  4. % File: PXK:FLOAT.C
  5. % Description: Miscellaneous floating point support routines.
  6. % Author: Leigh Stoller
  7. % Created: 29-Oct-86
  8. % Modified:
  9. % Mode: Text
  10. % Package:
  11. % Status: Open Source: BSD License
  12. %
  13. % (c) Copyright 1982, University of Utah
  14. %
  15. % Redistribution and use in source and binary forms, with or without
  16. % modification, are permitted provided that the following conditions are met:
  17. %
  18. % * Redistributions of source code must retain the relevant copyright
  19. % notice, this list of conditions and the following disclaimer.
  20. % * Redistributions in binary form must reproduce the above copyright
  21. % notice, this list of conditions and the following disclaimer in the
  22. % documentation and/or other materials provided with the distribution.
  23. %
  24. % THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. % AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  26. % THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  27. % PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNERS OR
  28. % CONTRIBUTORS
  29. % BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. % CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. % SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. % INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. % ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. % POSSIBILITY OF SUCH DAMAGE.
  36. %
  37. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  38. */
  39. /*
  40. * There used to be a collection of comments here describing revisions
  41. * made from about 1982 to 1989. I think those are by now of interest
  42. * to archaeologists! So anybody who wants to see them can consult older
  43. * copies of this file in the repositories. It is neverthless proper to
  44. * record the names of those who (in addition to the original author)
  45. * have contributed:
  46. * Leigh Stoller
  47. */
  48. #include <stdio.h>
  49. #include <string.h>
  50. #include <math.h>
  51. #include <fenv.h>
  52. #include <inttypes.h>
  53. #ifdef USE_CRLIBM
  54. #include "crlibm.h"
  55. #define sin sin_rn
  56. #define cos cos_rn
  57. #define tan tan_rn
  58. #define asin asin_rn
  59. #define acos acos_rn
  60. #define atan atan_rn
  61. #define exp exp_rn
  62. #define log log_rn
  63. #endif
  64. #include "psl.h"
  65. /* Tag( uxfloat )
  66. */
  67. void _(uxfloat)(double *f, int64_t i)
  68. { *f = i;
  69. }
  70. /* Tag( uxfix )
  71. */
  72. int64_t _(uxfix)(double *f)
  73. { return *f;
  74. }
  75. /* Tag( uxassign )
  76. */
  77. void _(uxassign)(double *f1, double *f2)
  78. { *f1 = *f2;
  79. }
  80. fexcept_t flagp;
  81. /* Tag( uxplus2 )
  82. */
  83. int _(uxplus2)(double *f1, double *f2, double *f3)
  84. { *f1 = *f2 + *f3;
  85. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  86. if(flagp != 0)
  87. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  88. return (0);
  89. }
  90. return (1);
  91. }
  92. /* Tag( uxdifference )
  93. */
  94. int _(uxdifference)(double *f1, double *f2, double *f3)
  95. { *f1 = *f2 - *f3;
  96. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  97. if(flagp != 0)
  98. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  99. return (0);
  100. }
  101. return (1);
  102. }
  103. /* Tag( uxtimes2 )
  104. */
  105. int _(uxtimes2)(double *f1, double *f2, double *f3)
  106. { *f1 = *f2 * *f3;
  107. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  108. if(flagp != 0)
  109. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  110. return (0);
  111. }
  112. return (1);
  113. }
  114. /* Tag( uxquotient )
  115. */
  116. int _(uxquotient)(double *f1, double *f2, double *f3)
  117. { *f1 = *f2 / *f3;
  118. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO | FE_INVALID);
  119. if(flagp != 0)
  120. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO | FE_INVALID);
  121. return (0);
  122. }
  123. return (1);
  124. }
  125. /* Tag( uxgreaterp )
  126. */
  127. int64_t _(uxgreaterp)(double *f1, double *f2, int64_t val1, int64_t val2)
  128. { if (*f1 > *f2) return val1;
  129. else return val2;
  130. }
  131. /* Tag( uxlessp )
  132. */
  133. int64_t _(uxlessp)(double *f1, double *f2, int64_t val1, int64_t val2)
  134. { if (*f1 < *f2) return val1;
  135. else return val2;
  136. }
  137. /* Tag( uxwritefloat )
  138. */
  139. void _(uxwritefloat)(char *buf, double *flt, const char *convstr)
  140. /* char *buf; String buffer to return float int */
  141. /* double *flt; Pointer to the float */
  142. /* char *convstr; String containing conversion field for sprintf */
  143. { char *temps, *dot, *e;
  144. char tempbuf[100]; /* reasonable size limit */
  145. temps = buf + 8; /* Skip over lisp string length to write data */
  146. sprintf(temps, convstr, *flt);
  147. if (isfinite(*flt))
  148. {
  149. /* Make sure that there is a trailing .0
  150. */
  151. dot = strrchr(temps, '.');
  152. if (dot == NULL)
  153. { /* Check to see if the number is in scientific notation. If so, we need
  154. * add the .0 into the middle of the string, just before the e.
  155. */
  156. if ((e = strrchr(temps, 'e')) || (e = strrchr(temps, 'E')))
  157. { strcpy(tempbuf, e); /* save exponent part */
  158. *e = '\0';
  159. strcat(temps, ".0"); /* Add .0 ono original string */
  160. strcat(temps, tempbuf); /* add the exponent part onto the end */
  161. }
  162. else
  163. { strcat(temps, ".0");
  164. }
  165. }
  166. }
  167. /* Install the length of the string into the Lisp header word
  168. */
  169. *((int64_t *)buf) = strlen(temps) - 1;
  170. }
  171. void _(uxwritefloat8)(char *buf, double *flt, const char *convstr, int dummy)
  172. /* char *buf; String buffer to return float int */
  173. /* double *flt; Pointer to the float */
  174. /* char *convstr; String containing conversion field for sprintf */
  175. /* int dummy; We need to have 128 bit alignemnt of the stack */
  176. { _(uxwritefloat)(buf, flt, convstr);
  177. }
  178. /* Tag( uxdoubletofloat )
  179. */
  180. void _(uxdoubletofloat)(double *dbl, float *flt)
  181. { *flt = (float) *dbl;
  182. }
  183. void _(uxfloattodouble)(float *flt, double *dbl)
  184. { *dbl = (double) *flt;
  185. }
  186. /* Functions for fast-math.sl (Unix C replacement for mathlib.) */
  187. int _(uxsin)(double *r, double *x)
  188. { *r = sin( *x );
  189. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  190. if(flagp != 0)
  191. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  192. return (0);
  193. }
  194. return (1);
  195. }
  196. int _(uxcos)(double *r, double *x)
  197. { *r = cos( *x );
  198. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  199. if(flagp != 0)
  200. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  201. return (0);
  202. }
  203. return (1);
  204. }
  205. int _(uxtan)(double *r, double *x)
  206. { *r = tan( *x );
  207. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  208. if(flagp != 0)
  209. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  210. return (0);
  211. }
  212. return (1);
  213. }
  214. int _(uxasin)(double *r, double *x)
  215. { *r = asin( *x );
  216. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  217. if(flagp != 0)
  218. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  219. return (0);
  220. }
  221. return (1);
  222. }
  223. int _(uxacos)(double *r, double *x)
  224. { *r = acos( *x );
  225. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  226. if(flagp != 0)
  227. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  228. return (0);
  229. }
  230. return (1);
  231. }
  232. int _(uxatan)(double *r, double *x)
  233. { *r = atan( *x );
  234. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  235. if(flagp != 0)
  236. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  237. return (0);
  238. }
  239. return (1);
  240. }
  241. int _(uxsqrt)(double *r, double *x)
  242. { *r = sqrt( *x );
  243. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  244. if(flagp != 0)
  245. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  246. return (0);
  247. }
  248. return (1);
  249. }
  250. int _(uxexp)(double *r, double *x)
  251. { *r = exp( *x );
  252. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  253. if(flagp != 0)
  254. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  255. return (0);
  256. }
  257. return (1);
  258. }
  259. int _(uxlog)(double *r, double *x)
  260. { *r = log( *x );
  261. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  262. if(flagp != 0)
  263. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  264. return (0);
  265. }
  266. return (1);
  267. }
  268. #define _pi ((12868.0 - 0.036490896206895257)/4096.0)
  269. #define _half_pi ((12868.0 - 0.036490896206895257)/8192.0)
  270. int _(uxatan2)(double *res, double *y, double *x)
  271. { double u=*x, v=*y, r;
  272. int q = 0;
  273. if (u < 0.0) u = -u, q = 1;
  274. if (v < 0.0) v = -v, q |= 2;
  275. if (v > u)
  276. { r = u;
  277. u = v;
  278. v = r;
  279. q |= 4;
  280. }
  281. if (u == 0.0 && v == 0.0) r = 0.0;
  282. else
  283. { r = atan(v/u);
  284. fegetexceptflag(&flagp, FE_OVERFLOW | FE_DIVBYZERO);
  285. if(flagp != 0)
  286. { feclearexcept(FE_OVERFLOW | FE_DIVBYZERO);
  287. return (0);
  288. }
  289. switch (q)
  290. { default:
  291. case 0: break;
  292. case 1: r = _pi - r;
  293. break;
  294. case 2: r = -r;
  295. break;
  296. case 3: r = -_pi + r;
  297. break;
  298. case 4: r = _half_pi - r;
  299. break;
  300. case 5: r = _half_pi + r;
  301. break;
  302. case 6: r = -_half_pi + r;
  303. break;
  304. case 7: r = -_half_pi - r;
  305. break;
  306. }
  307. }
  308. *res = r;
  309. return (1);
  310. }
  311. /* end of float.c */