Math.ob07 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2013-2014, 2018-2022 Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE Math;
  7. IMPORT SYSTEM;
  8. CONST
  9. pi* = 3.141592653589793;
  10. e* = 2.718281828459045;
  11. PROCEDURE IsNan* (x: REAL): BOOLEAN;
  12. VAR
  13. h, l: SET;
  14. BEGIN
  15. SYSTEM.GET(SYSTEM.ADR(x), l);
  16. SYSTEM.GET(SYSTEM.ADR(x) + 4, h)
  17. RETURN (h * {20..30} = {20..30}) & ((h * {0..19} # {}) OR (l * {0..31} # {}))
  18. END IsNan;
  19. PROCEDURE IsInf* (x: REAL): BOOLEAN;
  20. RETURN ABS(x) = SYSTEM.INF()
  21. END IsInf;
  22. PROCEDURE Max (a, b: REAL): REAL;
  23. VAR
  24. res: REAL;
  25. BEGIN
  26. IF a > b THEN
  27. res := a
  28. ELSE
  29. res := b
  30. END
  31. RETURN res
  32. END Max;
  33. PROCEDURE Min (a, b: REAL): REAL;
  34. VAR
  35. res: REAL;
  36. BEGIN
  37. IF a < b THEN
  38. res := a
  39. ELSE
  40. res := b
  41. END
  42. RETURN res
  43. END Min;
  44. PROCEDURE SameValue (a, b: REAL): BOOLEAN;
  45. VAR
  46. eps: REAL;
  47. res: BOOLEAN;
  48. BEGIN
  49. eps := Max(Min(ABS(a), ABS(b)) * 1.0E-12, 1.0E-12);
  50. IF a > b THEN
  51. res := (a - b) <= eps
  52. ELSE
  53. res := (b - a) <= eps
  54. END
  55. RETURN res
  56. END SameValue;
  57. PROCEDURE IsZero (x: REAL): BOOLEAN;
  58. RETURN ABS(x) <= 1.0E-12
  59. END IsZero;
  60. PROCEDURE [stdcall] sqrt* (x: REAL): REAL;
  61. BEGIN
  62. SYSTEM.CODE(
  63. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  64. 0D9H, 0FAH, (* fsqrt *)
  65. 0C9H, (* leave *)
  66. 0C2H, 008H, 000H (* ret 08h *)
  67. )
  68. RETURN 0.0
  69. END sqrt;
  70. PROCEDURE [stdcall] sin* (x: REAL): REAL;
  71. BEGIN
  72. SYSTEM.CODE(
  73. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  74. 0D9H, 0FEH, (* fsin *)
  75. 0C9H, (* leave *)
  76. 0C2H, 008H, 000H (* ret 08h *)
  77. )
  78. RETURN 0.0
  79. END sin;
  80. PROCEDURE [stdcall] cos* (x: REAL): REAL;
  81. BEGIN
  82. SYSTEM.CODE(
  83. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  84. 0D9H, 0FFH, (* fcos *)
  85. 0C9H, (* leave *)
  86. 0C2H, 008H, 000H (* ret 08h *)
  87. )
  88. RETURN 0.0
  89. END cos;
  90. PROCEDURE [stdcall] tan* (x: REAL): REAL;
  91. BEGIN
  92. SYSTEM.CODE(
  93. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  94. 0D9H, 0FBH, (* fsincos *)
  95. 0DEH, 0F9H, (* fdivp st1, st *)
  96. 0C9H, (* leave *)
  97. 0C2H, 008H, 000H (* ret 08h *)
  98. )
  99. RETURN 0.0
  100. END tan;
  101. PROCEDURE [stdcall] arctan2* (y, x: REAL): REAL;
  102. BEGIN
  103. SYSTEM.CODE(
  104. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  105. 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *)
  106. 0D9H, 0F3H, (* fpatan *)
  107. 0C9H, (* leave *)
  108. 0C2H, 010H, 000H (* ret 10h *)
  109. )
  110. RETURN 0.0
  111. END arctan2;
  112. PROCEDURE [stdcall] ln* (x: REAL): REAL;
  113. BEGIN
  114. SYSTEM.CODE(
  115. 0D9H, 0EDH, (* fldln2 *)
  116. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  117. 0D9H, 0F1H, (* fyl2x *)
  118. 0C9H, (* leave *)
  119. 0C2H, 008H, 000H (* ret 08h *)
  120. )
  121. RETURN 0.0
  122. END ln;
  123. PROCEDURE [stdcall] log* (base, x: REAL): REAL;
  124. BEGIN
  125. SYSTEM.CODE(
  126. 0D9H, 0E8H, (* fld1 *)
  127. 0DDH, 045H, 010H, (* fld qword [ebp + 10h] *)
  128. 0D9H, 0F1H, (* fyl2x *)
  129. 0D9H, 0E8H, (* fld1 *)
  130. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  131. 0D9H, 0F1H, (* fyl2x *)
  132. 0DEH, 0F9H, (* fdivp st1, st *)
  133. 0C9H, (* leave *)
  134. 0C2H, 010H, 000H (* ret 10h *)
  135. )
  136. RETURN 0.0
  137. END log;
  138. PROCEDURE [stdcall] exp* (x: REAL): REAL;
  139. BEGIN
  140. SYSTEM.CODE(
  141. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  142. 0D9H, 0EAH, (* fldl2e *)
  143. 0DEH, 0C9H, 0D9H, 0C0H,
  144. 0D9H, 0FCH, 0DCH, 0E9H,
  145. 0D9H, 0C9H, 0D9H, 0F0H,
  146. 0D9H, 0E8H, 0DEH, 0C1H,
  147. 0D9H, 0FDH, 0DDH, 0D9H,
  148. 0C9H, (* leave *)
  149. 0C2H, 008H, 000H (* ret 08h *)
  150. )
  151. RETURN 0.0
  152. END exp;
  153. PROCEDURE [stdcall] round* (x: REAL): REAL;
  154. BEGIN
  155. SYSTEM.CODE(
  156. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  157. 0D9H, 07DH, 0F4H, 0D9H,
  158. 07DH, 0F6H, 066H, 081H,
  159. 04DH, 0F6H, 000H, 003H,
  160. 0D9H, 06DH, 0F6H, 0D9H,
  161. 0FCH, 0D9H, 06DH, 0F4H,
  162. 0C9H, (* leave *)
  163. 0C2H, 008H, 000H (* ret 08h *)
  164. )
  165. RETURN 0.0
  166. END round;
  167. PROCEDURE [stdcall] frac* (x: REAL): REAL;
  168. BEGIN
  169. SYSTEM.CODE(
  170. 050H,
  171. 0DDH, 045H, 008H, (* fld qword [ebp + 08h] *)
  172. 0D9H, 0C0H, 0D9H, 03CH,
  173. 024H, 0D9H, 07CH, 024H,
  174. 002H, 066H, 081H, 04CH,
  175. 024H, 002H, 000H, 00FH,
  176. 0D9H, 06CH, 024H, 002H,
  177. 0D9H, 0FCH, 0D9H, 02CH,
  178. 024H, 0DEH, 0E9H,
  179. 0C9H, (* leave *)
  180. 0C2H, 008H, 000H (* ret 08h *)
  181. )
  182. RETURN 0.0
  183. END frac;
  184. PROCEDURE sqri* (x: INTEGER): INTEGER;
  185. RETURN x * x
  186. END sqri;
  187. PROCEDURE sqrr* (x: REAL): REAL;
  188. RETURN x * x
  189. END sqrr;
  190. PROCEDURE arcsin* (x: REAL): REAL;
  191. RETURN arctan2(x, sqrt(1.0 - x * x))
  192. END arcsin;
  193. PROCEDURE arccos* (x: REAL): REAL;
  194. RETURN arctan2(sqrt(1.0 - x * x), x)
  195. END arccos;
  196. PROCEDURE arctan* (x: REAL): REAL;
  197. RETURN arctan2(x, 1.0)
  198. END arctan;
  199. PROCEDURE sinh* (x: REAL): REAL;
  200. BEGIN
  201. x := exp(x)
  202. RETURN (x - 1.0 / x) * 0.5
  203. END sinh;
  204. PROCEDURE cosh* (x: REAL): REAL;
  205. BEGIN
  206. x := exp(x)
  207. RETURN (x + 1.0 / x) * 0.5
  208. END cosh;
  209. PROCEDURE tanh* (x: REAL): REAL;
  210. BEGIN
  211. IF x > 15.0 THEN
  212. x := 1.0
  213. ELSIF x < -15.0 THEN
  214. x := -1.0
  215. ELSE
  216. x := 1.0 - 2.0 / (exp(2.0 * x) + 1.0)
  217. END
  218. RETURN x
  219. END tanh;
  220. PROCEDURE arsinh* (x: REAL): REAL;
  221. RETURN ln(x + sqrt(x * x + 1.0))
  222. END arsinh;
  223. PROCEDURE arcosh* (x: REAL): REAL;
  224. RETURN ln(x + sqrt(x * x - 1.0))
  225. END arcosh;
  226. PROCEDURE artanh* (x: REAL): REAL;
  227. VAR
  228. res: REAL;
  229. BEGIN
  230. IF SameValue(x, 1.0) THEN
  231. res := SYSTEM.INF()
  232. ELSIF SameValue(x, -1.0) THEN
  233. res := -SYSTEM.INF()
  234. ELSE
  235. res := 0.5 * ln((1.0 + x) / (1.0 - x))
  236. END
  237. RETURN res
  238. END artanh;
  239. PROCEDURE floor* (x: REAL): REAL;
  240. VAR
  241. f: REAL;
  242. BEGIN
  243. f := frac(x);
  244. x := x - f;
  245. IF f < 0.0 THEN
  246. x := x - 1.0
  247. END
  248. RETURN x
  249. END floor;
  250. PROCEDURE ceil* (x: REAL): REAL;
  251. VAR
  252. f: REAL;
  253. BEGIN
  254. f := frac(x);
  255. x := x - f;
  256. IF f > 0.0 THEN
  257. x := x + 1.0
  258. END
  259. RETURN x
  260. END ceil;
  261. PROCEDURE power* (base, exponent: REAL): REAL;
  262. VAR
  263. res: REAL;
  264. BEGIN
  265. IF exponent = 0.0 THEN
  266. res := 1.0
  267. ELSIF (base = 0.0) & (exponent > 0.0) THEN
  268. res := 0.0
  269. ELSE
  270. res := exp(exponent * ln(base))
  271. END
  272. RETURN res
  273. END power;
  274. PROCEDURE ipower* (base: REAL; exponent: INTEGER): REAL;
  275. VAR
  276. i: INTEGER;
  277. a: REAL;
  278. BEGIN
  279. a := 1.0;
  280. IF base # 0.0 THEN
  281. IF exponent # 0 THEN
  282. IF exponent < 0 THEN
  283. base := 1.0 / base
  284. END;
  285. i := ABS(exponent);
  286. WHILE i > 0 DO
  287. WHILE ~ODD(i) DO
  288. i := LSR(i, 1);
  289. base := sqrr(base)
  290. END;
  291. DEC(i);
  292. a := a * base
  293. END
  294. ELSE
  295. a := 1.0
  296. END
  297. ELSE
  298. ASSERT(exponent > 0);
  299. a := 0.0
  300. END
  301. RETURN a
  302. END ipower;
  303. PROCEDURE sgn* (x: REAL): INTEGER;
  304. VAR
  305. res: INTEGER;
  306. BEGIN
  307. IF x > 0.0 THEN
  308. res := 1
  309. ELSIF x < 0.0 THEN
  310. res := -1
  311. ELSE
  312. res := 0
  313. END
  314. RETURN res
  315. END sgn;
  316. PROCEDURE fact* (n: INTEGER): REAL;
  317. VAR
  318. res: REAL;
  319. BEGIN
  320. res := 1.0;
  321. WHILE n > 1 DO
  322. res := res * FLT(n);
  323. DEC(n)
  324. END
  325. RETURN res
  326. END fact;
  327. PROCEDURE DegToRad* (x: REAL): REAL;
  328. RETURN x * (pi / 180.0)
  329. END DegToRad;
  330. PROCEDURE RadToDeg* (x: REAL): REAL;
  331. RETURN x * (180.0 / pi)
  332. END RadToDeg;
  333. (* Return hypotenuse of triangle *)
  334. PROCEDURE hypot* (x, y: REAL): REAL;
  335. VAR
  336. a: REAL;
  337. BEGIN
  338. x := ABS(x);
  339. y := ABS(y);
  340. IF x > y THEN
  341. a := x * sqrt(1.0 + sqrr(y / x))
  342. ELSE
  343. IF x > 0.0 THEN
  344. a := y * sqrt(1.0 + sqrr(x / y))
  345. ELSE
  346. a := y
  347. END
  348. END
  349. RETURN a
  350. END hypot;
  351. END Math.