123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- import { StoreObject } from '../store/storeObject';
- import * as Commands from './../../ast/commands';
- import { Types } from './../../typeSystem/types';
- import { toReal } from "./../../typeSystem/parsers";
- import { Decimal } from 'decimal.js';
- import { MultiType } from '../../typeSystem/multiType';
- import { CompoundType } from '../../typeSystem/compoundType';
- import { Modes } from '../modes';
- import { Config } from '../../util/config';
- /**
- * sin
- * cos
- * tan
- * sqrt
- * pow
- * log
- * abs
- * negate
- * invert
- * max
- * min
- */
- function convertToRadians (degrees) {
- return degrees.times(Decimal.acos(-1)).div(180);
- }
- export function createSinFun () {
- const sinFun = (sto, _) => {
- const x = sto.applyStore('x');
- const angle = x.value.mod(360);
- let result = null;
- if(angle.eq(90)) {
- result = new Decimal(1);
- } else if (angle.eq(180)) {
- result = new Decimal(0);
- } else if (angle.eq(270)) {
- result = new Decimal(-1);
- } else {
- result = Decimal.sin(convertToRadians(angle));
- }
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(sinFun)]);
- const func = new Commands.Function('$sin', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createCosFun () {
- const cosFun = (sto, _) => {
- const x = sto.applyStore('x');
- const angle = x.value.mod(360);
- let result = null;
- if(angle.eq(90)) {
- result = new Decimal(0);
- } else if (angle.eq(180)) {
- result = new Decimal(-1);
- } else if (angle.eq(270)) {
- result = new Decimal(0)
- }
- result = Decimal.cos(convertToRadians(angle));
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(cosFun)]);
- const func = new Commands.Function('$cos', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createTanFun () {
- const tanFun = (sto, _) => {
- const x = sto.applyStore('x');
- const angle = x.value.mod(360);
- if(angle.eq(90) || angle.eq(270)) {
- return Promise.reject("Tangent of "+x.value.toNumber()+"° is undefined.");
- }
- let result = Decimal.tan(convertToRadians(angle));
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(tanFun)]);
- const func = new Commands.Function('$tan', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createSqrtFun () {
- const sqrtFun = (sto, _) => {
- const x = sto.applyStore('x');
- let result = x.value.sqrt();
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(sqrtFun)]);
- const func = new Commands.Function('$sqrt', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createPowFun () {
- const powFun = (sto, _) => {
- const x = sto.applyStore('x');
- const y = sto.applyStore('y');
- let result = x.value.pow(y.value);
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(powFun)]);
- const func = new Commands.Function('$pow', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false),
- new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'y', false)],
- block);
- return func;
- }
- export function createLogFun () {
- const logFun = (sto, _) => {
- const x = sto.applyStore('x');
- if (x.value.isNegative()) {
- return Promise.reject(new Error("the value passed to log function cannot be negative"));
- }
- let result = Decimal.log10(x.value);
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(logFun)]);
- const func = new Commands.Function('$log', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createAbsFun () {
- const absFun = (sto, _) => {
- const x = sto.applyStore('x');
- const result = x.value.abs();
- const temp = new StoreObject(x.type, result);
- sto.updateStore('$', temp)
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto);
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(absFun)]);
- const func = new Commands.Function('$abs', new MultiType([Types.INTEGER, Types.REAL]),
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createNegateFun () {
- const negateFun = (sto, _) => {
- const x = sto.applyStore('x');
- const result = x.value.negated();
- const temp = new StoreObject(x.type, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(negateFun)]);
- const func = new Commands.Function('$negate', new MultiType([Types.INTEGER, Types.REAL]),
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createInvertFun () {
- const invertFun = (sto, _) => {
- const x = sto.applyStore('x');
- let result = toReal(1).dividedBy(x.value);
- if(result.dp() > Config.decimalPlaces) {
- result = new Decimal(result.toFixed(Config.decimalPlaces));
- }
- const temp = new StoreObject(Types.REAL, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const block = new Commands.CommandBlock([], [new Commands.SysCall(invertFun)]);
- const func = new Commands.Function('$invert', Types.REAL,
- [new Commands.FormalParameter(new MultiType([Types.INTEGER, Types.REAL]), 'x', false)],
- block);
- return func;
- }
- export function createMaxFun () {
- const maxFun = (sto, _) => {
- const x = sto.applyStore('x');
- const numbers = x.value.map(stoObj => stoObj.value);
- const result = Decimal.max(...numbers);
- const temp = new StoreObject(x.type.innerType, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const paramType = new CompoundType(new MultiType([Types.INTEGER, Types.REAL]), 1);
- const block = new Commands.CommandBlock([], [new Commands.SysCall(maxFun)]);
- const func = new Commands.Function('$max', new MultiType([Types.INTEGER, Types.REAL]),
- [new Commands.FormalParameter(paramType, 'x', false)],
- block);
- return func;
- }
- export function createMinFun () {
- const minFun = (sto, _) => {
- const x = sto.applyStore('x');
- const numbers = x.value.map(stoObj => stoObj.value);
- const result = Decimal.min(...numbers);
- const temp = new StoreObject(x.type.innerType, result);
- sto.mode = Modes.RETURN;
- return Promise.resolve(sto.updateStore('$', temp));
- };
- const paramType = new CompoundType(new MultiType([Types.INTEGER, Types.REAL]), 1);
- const block = new Commands.CommandBlock([], [new Commands.SysCall(minFun)]);
- const func = new Commands.Function('$min', new MultiType([Types.INTEGER, Types.REAL]),
- [new Commands.FormalParameter(paramType, 'x', false)],
- block);
- return func;
- }
|