math.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. import { StoreObject } from '../store/storeObject';
  2. import * as Commands from './../../ast/commands';
  3. import { Types } from './../../typeSystem/types';
  4. import { toReal } from "./../../typeSystem/parsers";
  5. import { Decimal } from 'decimal.js';
  6. import { MultiType } from '../../typeSystem/multiType';
  7. import { CompoundType } from '../../typeSystem/compoundType';
  8. import { Modes } from '../modes';
  9. import { Config } from '../../util/config';
  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.value.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. if(result.dp() > Config.decimalPlaces) {
  41. result = new Decimal(result.toFixed(Config.decimalPlaces));
  42. }
  43. const temp = new StoreObject(Types.REAL, result);
  44. sto.mode = Modes.RETURN;
  45. return Promise.resolve(sto.updateStore('$', temp));
  46. };
  47. const block = new Commands.CommandBlock([], [new Commands.SysCall(sinFun)]);
  48. const func = new Commands.Function('$sin', Types.REAL,
  49. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  50. block);
  51. return func;
  52. }
  53. export function createCosFun () {
  54. const cosFun = (sto, _) => {
  55. const x = sto.applyStore('x');
  56. const angle = x.value.mod(360);
  57. let result = null;
  58. if(angle.eq(90)) {
  59. result = new Decimal(0);
  60. } else if (angle.eq(180)) {
  61. result = new Decimal(-1);
  62. } else if (angle.eq(270)) {
  63. result = new Decimal(0)
  64. }
  65. result = Decimal.cos(convertToRadians(angle));
  66. if(result.dp() > Config.decimalPlaces) {
  67. result = new Decimal(result.toFixed(Config.decimalPlaces));
  68. }
  69. const temp = new StoreObject(Types.REAL, result);
  70. sto.mode = Modes.RETURN;
  71. return Promise.resolve(sto.updateStore('$', temp));
  72. };
  73. const block = new Commands.CommandBlock([], [new Commands.SysCall(cosFun)]);
  74. const func = new Commands.Function('$cos', Types.REAL,
  75. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  76. block);
  77. return func;
  78. }
  79. export function createTanFun () {
  80. const tanFun = (sto, _) => {
  81. const x = sto.applyStore('x');
  82. const angle = x.value.mod(360);
  83. if(angle.eq(90) || angle.eq(270)) {
  84. return Promise.reject("Tangent of "+x.value.toNumber()+"° is undefined.");
  85. }
  86. let result = Decimal.tan(convertToRadians(angle));
  87. if(result.dp() > Config.decimalPlaces) {
  88. result = new Decimal(result.toFixed(Config.decimalPlaces));
  89. }
  90. const temp = new StoreObject(Types.REAL, result);
  91. sto.mode = Modes.RETURN;
  92. return Promise.resolve(sto.updateStore('$', temp));
  93. };
  94. const block = new Commands.CommandBlock([], [new Commands.SysCall(tanFun)]);
  95. const func = new Commands.Function('$tan', Types.REAL,
  96. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  97. block);
  98. return func;
  99. }
  100. export function createSqrtFun () {
  101. const sqrtFun = (sto, _) => {
  102. const x = sto.applyStore('x');
  103. let result = x.value.sqrt();
  104. if(result.dp() > Config.decimalPlaces) {
  105. result = new Decimal(result.toFixed(Config.decimalPlaces));
  106. }
  107. const temp = new StoreObject(Types.REAL, result);
  108. sto.mode = Modes.RETURN;
  109. return Promise.resolve(sto.updateStore('$', temp));
  110. };
  111. const block = new Commands.CommandBlock([], [new Commands.SysCall(sqrtFun)]);
  112. const func = new Commands.Function('$sqrt', Types.REAL,
  113. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  114. block);
  115. return func;
  116. }
  117. export function createPowFun () {
  118. const powFun = (sto, _) => {
  119. const x = sto.applyStore('x');
  120. const y = sto.applyStore('y');
  121. let result = x.value.pow(y.value);
  122. if(result.dp() > Config.decimalPlaces) {
  123. result = new Decimal(result.toFixed(Config.decimalPlaces));
  124. }
  125. const temp = new StoreObject(Types.REAL, result);
  126. sto.mode = Modes.RETURN;
  127. return Promise.resolve(sto.updateStore('$', temp));
  128. };
  129. const block = new Commands.CommandBlock([], [new Commands.SysCall(powFun)]);
  130. const func = new Commands.Function('$pow', Types.REAL,
  131. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false),
  132. new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'y', false)],
  133. block);
  134. return func;
  135. }
  136. export function createLogFun () {
  137. const logFun = (sto, _) => {
  138. const x = sto.applyStore('x');
  139. if (x.value.isNegative()) {
  140. return Promise.reject("the value passed to log function cannot be negative");
  141. }
  142. let result = Decimal.log10(x.value);
  143. if(result.dp() > Config.decimalPlaces) {
  144. result = new Decimal(result.toFixed(Config.decimalPlaces));
  145. }
  146. const temp = new StoreObject(Types.REAL, result);
  147. sto.mode = Modes.RETURN;
  148. return Promise.resolve(sto.updateStore('$', temp));
  149. };
  150. const block = new Commands.CommandBlock([], [new Commands.SysCall(logFun)]);
  151. const func = new Commands.Function('$log', Types.REAL,
  152. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  153. block);
  154. return func;
  155. }
  156. export function createAbsFun () {
  157. const absFun = (sto, _) => {
  158. const x = sto.applyStore('x');
  159. const result = x.value.abs();
  160. const temp = new StoreObject(x.type, result);
  161. sto.mode = Modes.RETURN;
  162. return Promise.resolve(sto.updateStore('$', temp));
  163. };
  164. const block = new Commands.CommandBlock([], [new Commands.SysCall(absFun)]);
  165. const func = new Commands.Function('$abs', new MultiType([Types.INTEGER, Types.REAL]),
  166. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  167. block);
  168. return func;
  169. }
  170. export function createNegateFun () {
  171. const negateFun = (sto, _) => {
  172. const x = sto.applyStore('x');
  173. const result = x.value.negated();
  174. const temp = new StoreObject(x.type, result);
  175. sto.mode = Modes.RETURN;
  176. return Promise.resolve(sto.updateStore('$', temp));
  177. };
  178. const block = new Commands.CommandBlock([], [new Commands.SysCall(negateFun)]);
  179. const func = new Commands.Function('$negate', new MultiType([Types.INTEGER, Types.REAL]),
  180. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  181. block);
  182. return func;
  183. }
  184. export function createInvertFun () {
  185. const invertFun = (sto, _) => {
  186. const x = sto.applyStore('x');
  187. let result = toReal(1).dividedBy(x.value);
  188. if(result.dp() > Config.decimalPlaces) {
  189. result = new Decimal(result.toFixed(Config.decimalPlaces));
  190. }
  191. const temp = new StoreObject(Types.REAL, result);
  192. sto.mode = Modes.RETURN;
  193. return Promise.resolve(sto.updateStore('$', temp));
  194. };
  195. const block = new Commands.CommandBlock([], [new Commands.SysCall(invertFun)]);
  196. const func = new Commands.Function('$invert', Types.REAL,
  197. [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
  198. block);
  199. return func;
  200. }
  201. export function createMaxFun () {
  202. const maxFun = (sto, _) => {
  203. const x = sto.applyStore('x');
  204. const numbers = x.value.map(stoObj => stoObj.value);
  205. const result = Decimal.max(...numbers);
  206. const temp = new StoreObject(x.type.innerType, result);
  207. sto.mode = Modes.RETURN;
  208. return Promise.resolve(sto.updateStore('$', temp));
  209. };
  210. const paramType = new CompoundType(new MultiType([Types.INTEGER, Types.REAL]), 1);
  211. const block = new Commands.CommandBlock([], [new Commands.SysCall(maxFun)]);
  212. const func = new Commands.Function('$max', new MultiType([Types.INTEGER, Types.REAL]),
  213. [new Commands.FormalParameter(paramType, 'x', false)],
  214. block);
  215. return func;
  216. }
  217. export function createMinFun () {
  218. const minFun = (sto, _) => {
  219. const x = sto.applyStore('x');
  220. const numbers = x.value.map(stoObj => stoObj.value);
  221. const result = Decimal.min(...numbers);
  222. const temp = new StoreObject(x.type.innerType, result);
  223. sto.mode = Modes.RETURN;
  224. return Promise.resolve(sto.updateStore('$', temp));
  225. };
  226. const paramType = new CompoundType(new MultiType([Types.INTEGER, Types.REAL]), 1);
  227. const block = new Commands.CommandBlock([], [new Commands.SysCall(minFun)]);
  228. const func = new Commands.Function('$min', new MultiType([Types.INTEGER, Types.REAL]),
  229. [new Commands.FormalParameter(paramType, 'x', false)],
  230. block);
  231. return func;
  232. }