SMath.txt 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. MODULE SMath;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 System/Mod/SMatch.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM;
  5. VAR eps, e: SHORTREAL;
  6. (* code procedures for 80387 math coprocessor *)
  7. PROCEDURE [code] FLD (x: SHORTREAL);
  8. PROCEDURE [code] TOP (): SHORTREAL;
  9. PROCEDURE [code] FSW (): INTEGER 0DFH, 0E0H;
  10. PROCEDURE [code] FSWs (): SET 0DFH, 0E0H;
  11. PROCEDURE [code] ST0 (): SHORTREAL 0D9H, 0C0H;
  12. PROCEDURE [code] ST1 (): SHORTREAL 0D9H, 0C1H;
  13. PROCEDURE [code] FXCH 0D9H, 0C9H;
  14. PROCEDURE [code] FLDst0 0D9H, 0C0H; (* doublicate st[0] *)
  15. PROCEDURE [code] FSTPst0 0DDH, 0D8H; (* remove st[0] *)
  16. PROCEDURE [code] FSTPst1 0DDH, 0D9H; (* remove st[1] *)
  17. PROCEDURE [code] FSTPDe 0DBH, 05DH, 0F4H; (* FSTPD -12[FP] *) (* COMPILER DEPENDENT *)
  18. PROCEDURE [code] WAIT 09BH;
  19. PROCEDURE [code] FNOP 0D9H, 0D0H;
  20. PROCEDURE [code] FLD0 0D9H, 0EEH;
  21. PROCEDURE [code] FLD1 0D9H, 0E8H;
  22. PROCEDURE [code] FLDPI 0D9H, 0EBH;
  23. PROCEDURE [code] FLDLN2 0D9H, 0EDH;
  24. PROCEDURE [code] FLDLG2 0D9H, 0ECH;
  25. PROCEDURE [code] FLDL2E 0D9H, 0EAH;
  26. PROCEDURE [code] FADD 0DEH, 0C1H;
  27. PROCEDURE [code] FADDst0 0D8H, 0C0H;
  28. PROCEDURE [code] FSUB 0DEH, 0E9H;
  29. PROCEDURE [code] FSUBn 0DCH, 0E9H; (* no pop *)
  30. PROCEDURE [code] FSUBR 0DEH, 0E1H;
  31. PROCEDURE [code] FSUBst1 0D8H, 0E1H;
  32. PROCEDURE [code] FMUL 0DEH, 0C9H;
  33. PROCEDURE [code] FMULst0 0D8H, 0C8H;
  34. PROCEDURE [code] FMULst1st0 0DCH, 0C9H;
  35. PROCEDURE [code] FDIV 0DEH, 0F9H;
  36. PROCEDURE [code] FDIVR 0DEH, 0F1H;
  37. PROCEDURE [code] FDIVRst1 0D8H, 0F9H;
  38. PROCEDURE [code] FCHS 0D9H, 0E0H;
  39. PROCEDURE [code] FCOM 0D8H, 0D1H;
  40. PROCEDURE [code] FSWax 0DFH, 0E0H;
  41. PROCEDURE [code] SAHF 09EH;
  42. PROCEDURE [code] JBE4 076H, 004H;
  43. PROCEDURE [code] JAE4 073H, 004H;
  44. PROCEDURE [code] FRNDINT 0D9H, 0FCH;
  45. PROCEDURE [code] FSCALE 0D9H, 0FDH; (* st[0] * 2^FLOOR(st[1]) *)
  46. PROCEDURE [code] FXTRACT 0D9H, 0F4H; (* exp -> st[1]; mant -> st[0] *)
  47. PROCEDURE [code] FXAM 0D9H, 0E5H;
  48. PROCEDURE [code] FSQRT 0D9H, 0FAH; (* st[0] >= 0 *)
  49. PROCEDURE [code] FSIN 0D9H, 0FEH; (* |st[0]| < 2^63 *)
  50. PROCEDURE [code] FCOS 0D9H, 0FFH; (* |st[0]| < 2^63 *)
  51. PROCEDURE [code] FTAN 0D9H, 0F2H; (* |st[0]| < 2^63 *)
  52. PROCEDURE [code] FATAN 0D9H, 0F3H; (* atan2(st[1], st[0]) *)
  53. PROCEDURE [code] FYL2X 0D9H, 0F1H; (* st[1] * log2(st[0]), st[0] > 0 *)
  54. PROCEDURE [code] FYL2XP1 0D9H, 0F9H; (* st[1] * log2(1 + st[0]), |st[0]| < 1-sqrt(2)/2 *)
  55. PROCEDURE [code] F2XM1 0D9H, 0F0H; (* 2^st[0] - 1, |st[0]| <= 1 *)
  56. PROCEDURE IsNan (x: SHORTREAL): BOOLEAN;
  57. BEGIN
  58. FLD(x); FXAM; FSTPst0; WAIT; RETURN FSWs() * {8, 10} = {8}
  59. END IsNan;
  60. (* sin, cos, tan argument reduction *)
  61. PROCEDURE Reduce;
  62. BEGIN
  63. FXAM; WAIT;
  64. IF ~(8 IN FSWs()) & (ABS(ST0()) > 1.0E18) THEN
  65. (* to be completed *)
  66. FSTPst0; FLD0
  67. END;
  68. END Reduce;
  69. (** SHORTREAL precision **)
  70. PROCEDURE Pi* (): SHORTREAL;
  71. BEGIN
  72. FLDPI; RETURN TOP()
  73. END Pi;
  74. PROCEDURE Eps* (): SHORTREAL;
  75. BEGIN
  76. RETURN eps
  77. END Eps;
  78. PROCEDURE Sqrt* (x: SHORTREAL): SHORTREAL;
  79. BEGIN
  80. (* 20, argument of Sqrt must not be negative *)
  81. FLD(x); FSQRT; WAIT; RETURN TOP()
  82. END Sqrt;
  83. PROCEDURE Exp* (x: SHORTREAL): SHORTREAL;
  84. BEGIN
  85. (* 2 ^ (x * 1/ln(2)) *)
  86. FLD(x); FLDL2E; FMUL;
  87. IF ABS(ST0()) = INF THEN FLD1
  88. ELSE FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD
  89. END;
  90. FSCALE; FSTPst1; RETURN TOP()
  91. END Exp;
  92. PROCEDURE Ln* (x: SHORTREAL): SHORTREAL;
  93. BEGIN
  94. (* 20, argument of Ln must not be negative *)
  95. (* ln(2) * ld(x) *)
  96. FLDLN2; FLD(x); FYL2X; WAIT; RETURN TOP()
  97. END Ln;
  98. PROCEDURE Log* (x: SHORTREAL): SHORTREAL;
  99. BEGIN
  100. (* 20, argument of Log must not be negative *)
  101. (* log(2) * ld(x) *)
  102. FLDLG2; FLD(x); FYL2X; WAIT; RETURN TOP()
  103. END Log;
  104. PROCEDURE Power* (x, y: SHORTREAL): SHORTREAL;
  105. BEGIN
  106. ASSERT(x >= 0, 20);
  107. ASSERT((x # 0.0) OR (y # 0.0), 21);
  108. ASSERT((x # INF) OR (y # 0.0), 22);
  109. ASSERT((x # 1.0) OR (ABS(y) # INF), 23);
  110. (* 2 ^ (y * ld(x)) *)
  111. FLD(y); FLD(x); FYL2X;
  112. IF ABS(ST0()) = INF THEN FLD1
  113. ELSE FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD
  114. END;
  115. FSCALE; FSTPst1; WAIT; RETURN TOP()
  116. END Power;
  117. PROCEDURE IntPower* (x: SHORTREAL; n: INTEGER): SHORTREAL;
  118. BEGIN
  119. FLD1; FLD(x);
  120. IF n = MIN(INTEGER) THEN RETURN IntPower(x, n + 1) / x END;
  121. IF n <= 0 THEN FDIVRst1; (* 1 / x *) n := -n END;
  122. WHILE n > 0 DO
  123. IF ODD(n) THEN FMULst1st0; (* y := y * x *) DEC(n)
  124. ELSE FMULst0; (* x := x * x *) n := n DIV 2
  125. END
  126. END;
  127. FSTPst0; RETURN TOP()
  128. END IntPower;
  129. PROCEDURE Sin* (x: SHORTREAL): SHORTREAL;
  130. BEGIN
  131. (* 20, ABS(x) # INF *)
  132. FLD(x); Reduce; FSIN; WAIT; RETURN TOP()
  133. END Sin;
  134. PROCEDURE Cos* (x: SHORTREAL): SHORTREAL;
  135. BEGIN
  136. (* 20, ABS(x) # INF *)
  137. FLD(x); Reduce; FCOS; WAIT; RETURN TOP()
  138. END Cos;
  139. PROCEDURE Tan* (x: SHORTREAL): SHORTREAL;
  140. BEGIN
  141. (* 20, ABS(x) # INF *)
  142. FLD(x); Reduce; FTAN; FSTPst0; WAIT; RETURN TOP()
  143. END Tan;
  144. PROCEDURE ArcSin* (x: SHORTREAL): SHORTREAL;
  145. BEGIN
  146. (* 20, -1.0 <= x <= 1.0 *)
  147. (* atan2(x, sqrt(1 - x*x)) *)
  148. FLD(x); FLDst0; FMULst0; FLD1; FSUBR; FSQRT; FNOP; FATAN; WAIT; RETURN TOP()
  149. END ArcSin;
  150. PROCEDURE ArcCos* (x: SHORTREAL): SHORTREAL;
  151. BEGIN
  152. (* 20, -1.0 <= x <= 1.0 *)
  153. (* atan2(sqrt(1 - x*x), x) *)
  154. FLD(x); FMULst0; FLD1; FSUBR; FSQRT; FLD(x); FATAN; WAIT; RETURN TOP()
  155. END ArcCos;
  156. PROCEDURE ArcTan* (x: SHORTREAL): SHORTREAL;
  157. BEGIN
  158. (* atan2(x, 1) *)
  159. FLD(x); FLD1; FATAN; RETURN TOP()
  160. END ArcTan;
  161. PROCEDURE ArcTan2* (y, x: SHORTREAL): SHORTREAL;
  162. BEGIN
  163. ASSERT((y # 0) OR (x # 0), 20);
  164. ASSERT((ABS(y) # INF) OR (ABS(x) # INF), 21);
  165. FLD(y); FLD(x); FATAN; WAIT; RETURN TOP()
  166. END ArcTan2;
  167. PROCEDURE Sinh* (x: SHORTREAL): SHORTREAL;
  168. BEGIN
  169. (* IF IsNan(x) THEN RETURN x END; *)
  170. (* abs(x) * 1/ln(2) *)
  171. FLD(ABS(x)); FLDL2E; FMUL;
  172. IF ST0() < 0.5 THEN
  173. (* (2^z - 1) + (2^z - 1) / ((2^z - 1) + 1) *)
  174. F2XM1; FLDst0; FLDst0; FLD1; FADD; FDIV; FADD
  175. ELSIF ST0() # INF THEN
  176. (* 2^z - 1 / 2^z *)
  177. FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD; FSCALE;
  178. FSTPst1; FLDst0; FLD1; FDIVR; FSUB
  179. END;
  180. IF x < 0 THEN FCHS END;
  181. RETURN TOP() * 0.5
  182. END Sinh;
  183. PROCEDURE Cosh* (x: SHORTREAL): SHORTREAL;
  184. BEGIN
  185. (* IF IsNan(x) THEN RETURN x END; *)
  186. (* 2^(abs(x) * 1/ln(2)) *)
  187. FLD(ABS(x));
  188. IF ST0() # INF THEN
  189. FLDL2E; FMUL; FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD; FSCALE;
  190. FSTPst1;
  191. (* z + 1/z *)
  192. FLDst0; FLD1; FDIVR; FADD
  193. END;
  194. RETURN TOP() * 0.5
  195. END Cosh;
  196. PROCEDURE Tanh* (x: SHORTREAL): SHORTREAL;
  197. BEGIN
  198. (* IF IsNan(x) THEN RETURN x END; *)
  199. (* abs(x) * 1/ln(2) * 2 *)
  200. FLD(ABS(x)); FLDL2E; FMUL; FADDst0;
  201. IF ST0() < 0.5 THEN
  202. (* (2^z - 1) / (2^z + 1) *)
  203. F2XM1; FLDst0; FLD(2); FADD; FDIV
  204. ELSIF ST0() < 65 THEN
  205. (* 1 - 2 / (2^z + 1) *)
  206. FLDst0; FRNDINT; FXCH; FSUBst1; FNOP; F2XM1; FLD1; FADD; FSCALE; FSTPst1; FLD1; FADD; FLD(2); FDIVR; FLD1; FSUBR
  207. ELSE
  208. FSTPst0; FLD1
  209. END;
  210. IF x < 0 THEN FCHS END;
  211. RETURN TOP()
  212. END Tanh;
  213. PROCEDURE ArcSinh* (x: SHORTREAL): SHORTREAL;
  214. BEGIN
  215. (* IF IsNan(x) THEN RETURN x END; *)
  216. (* x*x *)
  217. FLDLN2; FLD(ABS(x)); FLDst0; FMULst0;
  218. IF ST0() < 0.067 THEN
  219. (* ln(2) * ld(1 + x*x / (sqrt(x*x + 1) + 1) + x) *)
  220. FLDst0; FLD1; FADD; FSQRT; FLD1; FADD; FDIV; FADD; FYL2XP1
  221. ELSE
  222. (* ln(2) * ld(x + sqrt(x*x + 1)) *)
  223. FLD1; FADD; FSQRT; FADD; FYL2X
  224. END;
  225. IF x < 0 THEN FCHS END;
  226. RETURN TOP()
  227. END ArcSinh;
  228. PROCEDURE ArcCosh* (x: SHORTREAL): SHORTREAL;
  229. BEGIN
  230. (* 20, x >= 1.0 *)
  231. (* IF IsNan(x) THEN RETURN x END; *)
  232. (* ln(2) * ld(x + sqrt(x*x - 1)) *)
  233. FLDLN2; FLD(x); FLDst0; FMULst0; FLD1; FSUB; FSQRT; FADD; FYL2X; WAIT; RETURN TOP()
  234. END ArcCosh;
  235. PROCEDURE ArcTanh* (x: SHORTREAL): SHORTREAL;
  236. BEGIN
  237. (* 20, -1.0 <= x <= 1.0 *)
  238. (* IF IsNan(x) THEN RETURN x END; *)
  239. (* |x| *)
  240. FLDLN2; FLD(ABS(x));
  241. IF ST0() < 0.12 THEN
  242. (* ln(2) * ld(1 + 2*x / (1 - x)) *)
  243. FLDst0; FLD1; FSUBR; FDIV; FADDst0; FYL2XP1
  244. ELSE
  245. (* ln(2) * ld((1 + x) / (1 - x)) *)
  246. FLDst0; FLD1; FADD; FXCH; FLD1; FSUBR; FDIV; FNOP; FYL2X
  247. END;
  248. IF x < 0 THEN FCHS END;
  249. WAIT;
  250. RETURN TOP() * 0.5
  251. END ArcTanh;
  252. PROCEDURE Floor* (x: SHORTREAL): SHORTREAL;
  253. BEGIN
  254. FLD(x); FLDst0; FRNDINT; FCOM; FSWax; FSTPst1; SAHF; JBE4; FLD1; FSUB; RETURN TOP()
  255. END Floor;
  256. PROCEDURE Ceiling* (x: SHORTREAL): SHORTREAL;
  257. BEGIN
  258. FLD(x); FLDst0; FRNDINT; FCOM; FSWax; FSTPst1; SAHF; JAE4; FLD1; FADD; RETURN TOP()
  259. END Ceiling;
  260. PROCEDURE Round* (x: SHORTREAL): SHORTREAL;
  261. BEGIN
  262. FLD(x);
  263. IF ABS(ST0()) = INF THEN RETURN TOP() END;
  264. FLDst0; FRNDINT; FSUBn; FXCH;
  265. IF TOP() = 0.5 THEN FLD1; FADD END;
  266. RETURN TOP()
  267. END Round;
  268. PROCEDURE Trunc* (x: SHORTREAL): SHORTREAL;
  269. BEGIN
  270. FLD(x); FLDst0; FRNDINT;
  271. IF ST1() >= 0 THEN
  272. FCOM; FSWax; FSTPst1; SAHF; JBE4; FLD1; FSUB
  273. ELSE
  274. FCOM; FSWax; FSTPst1; SAHF; JAE4; FLD1; FADD
  275. END;
  276. RETURN TOP()
  277. END Trunc;
  278. PROCEDURE Frac* (x: SHORTREAL): SHORTREAL;
  279. BEGIN
  280. (* 20, x # INF & x # -INF *)
  281. FLD(x); FLDst0; FRNDINT;
  282. IF ST1() >= 0 THEN
  283. FCOM; FSWax; SAHF; JBE4; FLD1; FSUB
  284. ELSE
  285. FCOM; FSWax; SAHF; JAE4; FLD1; FADD
  286. END;
  287. FSUB; WAIT; RETURN TOP()
  288. END Frac;
  289. PROCEDURE Sign* (x: SHORTREAL): SHORTREAL;
  290. BEGIN
  291. FLD(x); FXAM; WAIT;
  292. CASE FSW() DIV 256 MOD 8 OF
  293. | 0, 2: FSTPst0; RETURN 0.0
  294. | 1, 4, 5: FSTPst0; RETURN 1.0
  295. | 3, 6, 7: FSTPst0; RETURN -1.0
  296. END
  297. END Sign;
  298. PROCEDURE Mantissa* (x: SHORTREAL): SHORTREAL;
  299. BEGIN
  300. FLD(x); FXAM; WAIT;
  301. CASE FSW() DIV 256 MOD 8 OF
  302. | 4, 6: FXTRACT; FSTPst1; RETURN TOP()
  303. | 0, 2: FSTPst0; RETURN 0.0 (* zero *)
  304. | 5: FSTPst0; RETURN 1.0 (* inf *)
  305. | 7: FSTPst0; RETURN -1.0 (* -inf *)
  306. | 1: FSTPst0; RETURN 1.5 (* nan *)
  307. | 3: FSTPst0; RETURN -1.5 (* -nan *)
  308. END
  309. END Mantissa;
  310. PROCEDURE Exponent* (x: SHORTREAL): INTEGER; (* COMPILER DEPENDENT *)
  311. VAR e: INTEGER; (* e is set by FSTPDe! *)
  312. BEGIN
  313. FLD(x); FXAM; WAIT;
  314. CASE FSW() DIV 256 MOD 8 OF
  315. | 4, 6: FXTRACT; FSTPst0; FSTPDe; WAIT; RETURN e
  316. | 0, 2: FSTPst0; RETURN 0 (* zero *)
  317. | 1, 3, 5, 7: FSTPst0; RETURN MAX(INTEGER) (* inf or nan*)
  318. END
  319. END Exponent;
  320. PROCEDURE Real* (m: SHORTREAL; e: INTEGER): SHORTREAL;
  321. VAR s: SET;
  322. BEGIN
  323. IF (m = 0) THEN RETURN 0.0 END;
  324. ASSERT(~IsNan(m) & (1 <= ABS(m)) & (ABS(m) < 2), 20);
  325. IF e = MAX(INTEGER) THEN
  326. SYSTEM.GET(SYSTEM.ADR(m) + 4, s);
  327. SYSTEM.PUT(SYSTEM.ADR(m) + 4, s + {20..30});
  328. RETURN m
  329. ELSE
  330. FLD(e); FLD(m); FSCALE; FSTPst1; RETURN TOP()
  331. END
  332. END Real;
  333. BEGIN
  334. eps := 1.0E+0; e := 2.0E+0;
  335. WHILE e > 1.0E+0 DO eps := eps/2.0E+0; e := 1.0E+0 + eps END; eps := 2.0E+0 * eps;
  336. END SMath.