math.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import * as Commands from "./../../ast/commands";
  2. import { Types } from "./../../typeSystem/types";
  3. import { toReal } from "./../../typeSystem/parsers";
  4. import { Decimal } from "decimal.js";
  5. import { MultiType } from "../../typeSystem/multiType";
  6. import { ArrayType } from "../../typeSystem/array_type";
  7. import { Modes } from "../modes";
  8. import { StoreValue } from "../store/value/store_value";
  9. import { ProcessorErrorFactory } from "../error/processorErrorFactory";
  10. /**
  11. * sin
  12. * cos
  13. * tan
  14. * sqrt
  15. * pow
  16. * log
  17. * abs
  18. * negate
  19. * invert
  20. * max
  21. * min
  22. */
  23. function convertToRadians(degrees) {
  24. return degrees.times(Decimal.acos(-1)).div(180);
  25. }
  26. export function createSinFun() {
  27. const sinFun = (sto, _) => {
  28. const x = sto.applyStore("x");
  29. const angle = x.get().mod(360);
  30. let result = null;
  31. if (angle.eq(90)) {
  32. result = new Decimal(1);
  33. } else if (angle.eq(180)) {
  34. result = new Decimal(0);
  35. } else if (angle.eq(270)) {
  36. result = new Decimal(-1);
  37. } else {
  38. result = Decimal.sin(convertToRadians(angle));
  39. }
  40. const temp = new StoreValue(Types.REAL, result);
  41. sto.insertStore("$", temp);
  42. sto.mode = Modes.RETURN;
  43. return Promise.resolve(sto);
  44. };
  45. const block = new Commands.CommandBlock([], [new Commands.SysCall(sinFun)]);
  46. const func = new Commands.Function(
  47. "$sin",
  48. Types.REAL,
  49. [
  50. new Commands.FormalParameter(
  51. new MultiType([Types.INTEGER, Types.REAL]),
  52. "x",
  53. false
  54. )
  55. ],
  56. block
  57. );
  58. return func;
  59. }
  60. export function createCosFun() {
  61. const cosFun = (sto, _) => {
  62. const x = sto.applyStore("x");
  63. const angle = x.get().mod(360);
  64. let result = null;
  65. if (angle.eq(90)) {
  66. result = new Decimal(0);
  67. } else if (angle.eq(180)) {
  68. result = new Decimal(-1);
  69. } else if (angle.eq(270)) {
  70. result = new Decimal(0);
  71. }
  72. result = Decimal.cos(convertToRadians(angle));
  73. const temp = new StoreValue(Types.REAL, result);
  74. sto.insertStore("$", temp);
  75. sto.mode = Modes.RETURN;
  76. return Promise.resolve(sto);
  77. };
  78. const block = new Commands.CommandBlock([], [new Commands.SysCall(cosFun)]);
  79. const func = new Commands.Function(
  80. "$cos",
  81. Types.REAL,
  82. [
  83. new Commands.FormalParameter(
  84. new MultiType([Types.INTEGER, Types.REAL]),
  85. "x",
  86. false
  87. )
  88. ],
  89. block
  90. );
  91. return func;
  92. }
  93. export function createTanFun() {
  94. const tanFun = function(sto, _) {
  95. const x = sto.applyStore("x");
  96. const angle = x.get().mod(360);
  97. if (angle.eq(90) || angle.eq(270)) {
  98. return Promise.reject(
  99. ProcessorErrorFactory.undefined_tanget_value(
  100. x.get().toNumber(),
  101. this.function_call_stack.pop()
  102. )
  103. );
  104. }
  105. const result = Decimal.tan(convertToRadians(angle));
  106. const temp = new StoreValue(Types.REAL, result);
  107. sto.insertStore("$", temp);
  108. sto.mode = Modes.RETURN;
  109. return Promise.resolve(sto);
  110. };
  111. const block = new Commands.CommandBlock([], [new Commands.SysCall(tanFun)]);
  112. const func = new Commands.Function(
  113. "$tan",
  114. Types.REAL,
  115. [
  116. new Commands.FormalParameter(
  117. new MultiType([Types.INTEGER, Types.REAL]),
  118. "x",
  119. false
  120. )
  121. ],
  122. block
  123. );
  124. return func;
  125. }
  126. export function createSqrtFun() {
  127. const sqrtFun = function(sto, _) {
  128. const x = sto.applyStore("x");
  129. if (x.get().isNeg()) {
  130. return Promise.reject(
  131. ProcessorErrorFactory.negative_sqrt_value(
  132. this.function_call_stack.pop()
  133. )
  134. );
  135. }
  136. const result = x.get().sqrt();
  137. const temp = new StoreValue(Types.REAL, result);
  138. sto.insertStore("$", temp);
  139. sto.mode = Modes.RETURN;
  140. return Promise.resolve(sto);
  141. };
  142. const block = new Commands.CommandBlock([], [new Commands.SysCall(sqrtFun)]);
  143. const func = new Commands.Function(
  144. "$sqrt",
  145. Types.REAL,
  146. [
  147. new Commands.FormalParameter(
  148. new MultiType([Types.INTEGER, Types.REAL]),
  149. "x",
  150. false
  151. )
  152. ],
  153. block
  154. );
  155. return func;
  156. }
  157. export function createPowFun() {
  158. const powFun = (sto, _) => {
  159. const x = sto.applyStore("x");
  160. const y = sto.applyStore("y");
  161. const result = x.get().pow(y.get());
  162. const temp = new StoreValue(Types.REAL, result);
  163. sto.insertStore("$", temp);
  164. sto.mode = Modes.RETURN;
  165. return Promise.resolve(sto);
  166. };
  167. const block = new Commands.CommandBlock([], [new Commands.SysCall(powFun)]);
  168. const func = new Commands.Function(
  169. "$pow",
  170. Types.REAL,
  171. [
  172. new Commands.FormalParameter(
  173. new MultiType([Types.INTEGER, Types.REAL]),
  174. "x",
  175. false
  176. ),
  177. new Commands.FormalParameter(
  178. new MultiType([Types.INTEGER, Types.REAL]),
  179. "y",
  180. false
  181. )
  182. ],
  183. block
  184. );
  185. return func;
  186. }
  187. export function createLogFun() {
  188. const logFun = function(sto, _) {
  189. const x = sto.applyStore("x");
  190. if (x.get().isNegative()) {
  191. return Promise.reject(
  192. ProcessorErrorFactory.negative_log_value(this.function_call_stack.pop())
  193. );
  194. }
  195. const result = Decimal.log10(x.get());
  196. const temp = new StoreValue(Types.REAL, result);
  197. sto.insertStore("$", temp);
  198. sto.mode = Modes.RETURN;
  199. return Promise.resolve(sto);
  200. };
  201. const block = new Commands.CommandBlock([], [new Commands.SysCall(logFun)]);
  202. const func = new Commands.Function(
  203. "$log",
  204. Types.REAL,
  205. [
  206. new Commands.FormalParameter(
  207. new MultiType([Types.INTEGER, Types.REAL]),
  208. "x",
  209. false
  210. )
  211. ],
  212. block
  213. );
  214. return func;
  215. }
  216. export function createAbsFun() {
  217. const absFun = (sto, _) => {
  218. const x = sto.applyStore("x");
  219. const result = x.get().abs();
  220. const temp = new StoreValue(x.type, result);
  221. sto.insertStore("$", temp);
  222. sto.mode = Modes.RETURN;
  223. return Promise.resolve(sto);
  224. };
  225. const block = new Commands.CommandBlock([], [new Commands.SysCall(absFun)]);
  226. const func = new Commands.Function(
  227. "$abs",
  228. new MultiType([Types.INTEGER, Types.REAL]),
  229. [
  230. new Commands.FormalParameter(
  231. new MultiType([Types.INTEGER, Types.REAL]),
  232. "x",
  233. false
  234. )
  235. ],
  236. block
  237. );
  238. return func;
  239. }
  240. export function createNegateFun() {
  241. const negateFun = (sto, _) => {
  242. const x = sto.applyStore("x");
  243. const result = x.get().negated();
  244. const temp = new StoreValue(x.type, result);
  245. sto.insertStore("$", temp);
  246. sto.mode = Modes.RETURN;
  247. return Promise.resolve(sto);
  248. };
  249. const block = new Commands.CommandBlock(
  250. [],
  251. [new Commands.SysCall(negateFun)]
  252. );
  253. const func = new Commands.Function(
  254. "$negate",
  255. new MultiType([Types.INTEGER, Types.REAL]),
  256. [
  257. new Commands.FormalParameter(
  258. new MultiType([Types.INTEGER, Types.REAL]),
  259. "x",
  260. false
  261. )
  262. ],
  263. block
  264. );
  265. return func;
  266. }
  267. export function createInvertFun() {
  268. const invertFun = (sto, _) => {
  269. const x = sto.applyStore("x");
  270. const result = toReal(1).dividedBy(x.get());
  271. const temp = new StoreValue(Types.REAL, result);
  272. sto.insertStore("$", temp);
  273. sto.mode = Modes.RETURN;
  274. return Promise.resolve(sto);
  275. };
  276. const block = new Commands.CommandBlock(
  277. [],
  278. [new Commands.SysCall(invertFun)]
  279. );
  280. const func = new Commands.Function(
  281. "$invert",
  282. Types.REAL,
  283. [
  284. new Commands.FormalParameter(
  285. new MultiType([Types.INTEGER, Types.REAL]),
  286. "x",
  287. false
  288. )
  289. ],
  290. block
  291. );
  292. return func;
  293. }
  294. export function createMaxFun() {
  295. const maxFun = (sto, _) => {
  296. const x = sto.applyStore("x");
  297. const numbers = x.get().map(sto_addrs => sto_addrs.get());
  298. const result = Decimal.max(...numbers);
  299. const temp = new StoreValue(x.type.innerType, result);
  300. sto.insertStore("$", temp);
  301. sto.mode = Modes.RETURN;
  302. return Promise.resolve(sto);
  303. };
  304. const paramType = new ArrayType(
  305. new MultiType([Types.INTEGER, Types.REAL]),
  306. 1
  307. );
  308. const block = new Commands.CommandBlock([], [new Commands.SysCall(maxFun)]);
  309. const func = new Commands.Function(
  310. "$max",
  311. new MultiType([Types.INTEGER, Types.REAL]),
  312. [new Commands.FormalParameter(paramType, "x", false)],
  313. block
  314. );
  315. return func;
  316. }
  317. export function createMinFun() {
  318. const minFun = (sto, _) => {
  319. const x = sto.applyStore("x");
  320. const numbers = x.get().map(sto_addrs => sto_addrs.get());
  321. const result = Decimal.min(...numbers);
  322. const temp = new StoreValue(x.type.innerType, result);
  323. sto.insertStore("$", temp);
  324. sto.mode = Modes.RETURN;
  325. return Promise.resolve(sto);
  326. };
  327. const paramType = new ArrayType(
  328. new MultiType([Types.INTEGER, Types.REAL]),
  329. 1
  330. );
  331. const block = new Commands.CommandBlock([], [new Commands.SysCall(minFun)]);
  332. const func = new Commands.Function(
  333. "$min",
  334. new MultiType([Types.INTEGER, Types.REAL]),
  335. [new Commands.FormalParameter(paramType, "x", false)],
  336. block
  337. );
  338. return func;
  339. }
  340. let seed = Date.now();
  341. export function createRandFun() {
  342. const a = 16807;
  343. const m = 2147483647;
  344. const c = 12345;
  345. const randFun = (sto, _) => {
  346. seed = (a * seed + c) % m;
  347. const val = seed / (m - 1);
  348. const temp = new StoreValue(Types.REAL, new Decimal(val));
  349. sto.insertStore("$", temp);
  350. sto.mode = Modes.RETURN;
  351. return Promise.resolve(sto);
  352. };
  353. const block = new Commands.CommandBlock([], [new Commands.SysCall(randFun)]);
  354. const func = new Commands.Function("$rand", Types.REAL, [], block);
  355. return func;
  356. }
  357. export function createSetSeedFun() {
  358. const setSeedFun = (sto, _) => {
  359. const value = sto.applyStore("x");
  360. seed = value.get().toNumber();
  361. sto.mode = Modes.RETURN;
  362. return Promise.resolve(sto);
  363. };
  364. const block = new Commands.CommandBlock(
  365. [],
  366. [new Commands.SysCall(setSeedFun)]
  367. );
  368. const func = new Commands.Function(
  369. "$setSeed",
  370. Types.VOID,
  371. [new Commands.FormalParameter(Types.INTEGER, "x", false)],
  372. block
  373. );
  374. return func;
  375. }