math.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. import * as Commands from './../../ast/commands';
  2. import { Types } from './../../typeSystem/types';
  3. import * as Parsers 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 = async (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 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 = async (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 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 = async function (sto, _) {
  95. const x = sto.applyStore('x');
  96. const angle = x.get().mod(360);
  97. if(angle.eq(90) || angle.eq(270)) {
  98. throw ProcessorErrorFactory.undefined_tanget_value(x.get().toNumber(),
  99. this.function_call_stack.pop());
  100. }
  101. const result = Decimal.tan(convertToRadians(angle));
  102. const temp = new StoreValue(Types.REAL, result);
  103. sto.insertStore("$", temp);
  104. sto.mode = Modes.RETURN;
  105. return sto;
  106. };
  107. const block = new Commands.CommandBlock([], [new Commands.SysCall(tanFun)]);
  108. const func = new Commands.Function(
  109. "$tan",
  110. Types.REAL,
  111. [
  112. new Commands.FormalParameter(
  113. new MultiType([Types.INTEGER, Types.REAL]),
  114. "x",
  115. false
  116. )
  117. ],
  118. block
  119. );
  120. return func;
  121. }
  122. export function createSqrtFun () {
  123. const sqrtFun = async function (sto, _) {
  124. const x = sto.applyStore('x');
  125. if(x.get().isNeg()) {
  126. return Promise.reject(ProcessorErrorFactory.negative_sqrt_value(this.function_call_stack.pop()));
  127. }
  128. const result = x.get().sqrt();
  129. const temp = new StoreValue(Types.REAL, result);
  130. sto.insertStore("$", temp);
  131. sto.mode = Modes.RETURN;
  132. return sto;
  133. };
  134. const block = new Commands.CommandBlock([], [new Commands.SysCall(sqrtFun)]);
  135. const func = new Commands.Function(
  136. "$sqrt",
  137. Types.REAL,
  138. [
  139. new Commands.FormalParameter(
  140. new MultiType([Types.INTEGER, Types.REAL]),
  141. "x",
  142. false
  143. )
  144. ],
  145. block
  146. );
  147. return func;
  148. }
  149. export function createPowFun () {
  150. const powFun = async (sto, _) => {
  151. const x = sto.applyStore('x');
  152. const y = sto.applyStore('y');
  153. const result = x.get().pow(y.get());
  154. const temp = new StoreValue(Types.REAL, result);
  155. sto.insertStore("$", temp);
  156. sto.mode = Modes.RETURN;
  157. return sto;
  158. };
  159. const block = new Commands.CommandBlock([], [new Commands.SysCall(powFun)]);
  160. const func = new Commands.Function(
  161. "$pow",
  162. Types.REAL,
  163. [
  164. new Commands.FormalParameter(
  165. new MultiType([Types.INTEGER, Types.REAL]),
  166. "x",
  167. false
  168. ),
  169. new Commands.FormalParameter(
  170. new MultiType([Types.INTEGER, Types.REAL]),
  171. "y",
  172. false
  173. )
  174. ],
  175. block
  176. );
  177. return func;
  178. }
  179. export function createLogFun () {
  180. const logFun = async function (sto, _) {
  181. const x = sto.applyStore('x');
  182. if (x.get().isNegative()) {
  183. return Promise.reject(
  184. ProcessorErrorFactory.negative_log_value(this.function_call_stack.pop())
  185. );
  186. }
  187. const result = Decimal.log10(x.get());
  188. const temp = new StoreValue(Types.REAL, result);
  189. sto.insertStore("$", temp);
  190. sto.mode = Modes.RETURN;
  191. return sto;
  192. };
  193. const block = new Commands.CommandBlock([], [new Commands.SysCall(logFun)]);
  194. const func = new Commands.Function(
  195. "$log",
  196. Types.REAL,
  197. [
  198. new Commands.FormalParameter(
  199. new MultiType([Types.INTEGER, Types.REAL]),
  200. "x",
  201. false
  202. )
  203. ],
  204. block
  205. );
  206. return func;
  207. }
  208. export function createAbsFun () {
  209. const absFun = async (sto, _) => {
  210. const x = sto.applyStore('x');
  211. const result = x.get().abs();
  212. const temp = new StoreValue(x.type, result);
  213. sto.insertStore("$", temp);
  214. sto.mode = Modes.RETURN;
  215. return sto;
  216. };
  217. const block = new Commands.CommandBlock([], [new Commands.SysCall(absFun)]);
  218. const func = new Commands.Function(
  219. "$abs",
  220. new MultiType([Types.INTEGER, Types.REAL]),
  221. [
  222. new Commands.FormalParameter(
  223. new MultiType([Types.INTEGER, Types.REAL]),
  224. "x",
  225. false
  226. )
  227. ],
  228. block
  229. );
  230. return func;
  231. }
  232. export function createNegateFun () {
  233. const negateFun = async (sto, _) => {
  234. const x = sto.applyStore('x');
  235. const result = x.get().negated();
  236. const temp = new StoreValue(x.type, result);
  237. sto.insertStore("$", temp);
  238. sto.mode = Modes.RETURN;
  239. return sto;
  240. };
  241. const block = new Commands.CommandBlock(
  242. [],
  243. [new Commands.SysCall(negateFun)]
  244. );
  245. const func = new Commands.Function(
  246. "$negate",
  247. new MultiType([Types.INTEGER, Types.REAL]),
  248. [
  249. new Commands.FormalParameter(
  250. new MultiType([Types.INTEGER, Types.REAL]),
  251. "x",
  252. false
  253. )
  254. ],
  255. block
  256. );
  257. return func;
  258. }
  259. export function createInvertFun() {
  260. const invertFun = async (sto, _) => {
  261. const x = sto.applyStore('x');
  262. const result = Parsers.toReal(1).dividedBy(x.get());
  263. const temp = new StoreValue(Types.REAL, result);
  264. sto.insertStore("$", temp);
  265. sto.mode = Modes.RETURN;
  266. return sto;
  267. };
  268. const block = new Commands.CommandBlock(
  269. [],
  270. [new Commands.SysCall(invertFun)]
  271. );
  272. const func = new Commands.Function(
  273. "$invert",
  274. Types.REAL,
  275. [
  276. new Commands.FormalParameter(
  277. new MultiType([Types.INTEGER, Types.REAL]),
  278. "x",
  279. false
  280. )
  281. ],
  282. block
  283. );
  284. return func;
  285. }
  286. export function createMaxFun () {
  287. const maxFun = async (sto, _) => {
  288. const x = sto.applyStore('x');
  289. const numbers = x.get().map(sto_addrs => sto_addrs.get());
  290. const result = Decimal.max(...numbers);
  291. const temp = new StoreValue(x.type.innerType, result);
  292. sto.insertStore("$", temp);
  293. sto.mode = Modes.RETURN;
  294. return sto;
  295. };
  296. const paramType = new ArrayType(
  297. new MultiType([Types.INTEGER, Types.REAL]),
  298. 1
  299. );
  300. const block = new Commands.CommandBlock([], [new Commands.SysCall(maxFun)]);
  301. const func = new Commands.Function(
  302. "$max",
  303. new MultiType([Types.INTEGER, Types.REAL]),
  304. [new Commands.FormalParameter(paramType, "x", false)],
  305. block
  306. );
  307. return func;
  308. }
  309. export function createMinFun () {
  310. const minFun = async (sto, _) => {
  311. const x = sto.applyStore('x');
  312. const numbers = x.get().map(sto_addrs => sto_addrs.get());
  313. const result = Decimal.min(...numbers);
  314. const temp = new StoreValue(x.type.innerType, result);
  315. sto.insertStore("$", temp);
  316. sto.mode = Modes.RETURN;
  317. return sto;
  318. };
  319. const paramType = new ArrayType(
  320. new MultiType([Types.INTEGER, Types.REAL]),
  321. 1
  322. );
  323. const block = new Commands.CommandBlock([], [new Commands.SysCall(minFun)]);
  324. const func = new Commands.Function(
  325. "$min",
  326. new MultiType([Types.INTEGER, Types.REAL]),
  327. [new Commands.FormalParameter(paramType, "x", false)],
  328. block
  329. );
  330. return func;
  331. }
  332. let seed = Date.now();
  333. export function createRandFun() {
  334. const a = 16807;
  335. const m = 2147483647;
  336. const c = 12345;
  337. const randFun = async (sto, _) => {
  338. seed = (a * seed + c) % m;
  339. const val = seed / (m - 1);
  340. const temp = new StoreValue(Types.REAL, new Decimal(val));
  341. sto.insertStore("$", temp);
  342. sto.mode = Modes.RETURN;
  343. return sto;
  344. };
  345. const block = new Commands.CommandBlock([], [new Commands.SysCall(randFun)]);
  346. const func = new Commands.Function("$rand", Types.REAL, [], block);
  347. return func;
  348. }
  349. export function createSetSeedFun() {
  350. const setSeedFun = async (sto, _) => {
  351. const value = sto.applyStore("x");
  352. seed = value.get().toNumber();
  353. sto.mode = Modes.RETURN;
  354. return sto;
  355. };
  356. const block = new Commands.CommandBlock(
  357. [],
  358. [new Commands.SysCall(setSeedFun)]
  359. );
  360. const func = new Commands.Function(
  361. "$setSeed",
  362. Types.VOID,
  363. [new Commands.FormalParameter(Types.INTEGER, "x", false)],
  364. block
  365. );
  366. return func;
  367. }