Browse Source

Implement a lcg for the random generator

Lucas de Souza 5 years ago
parent
commit
990d2681f2
1 changed files with 258 additions and 119 deletions
  1. 258 119
      js/processor/lib/math.js

+ 258 - 119
js/processor/lib/math.js

@@ -1,12 +1,12 @@
-import * as Commands from './../../ast/commands';
-import { Types } from './../../typeSystem/types';
+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 { ArrayType } from '../../typeSystem/array_type';
-import { Modes } from '../modes';
-import { StoreValue } from '../store/value/store_value';
-import { ProcessorErrorFactory } from '../error/processorErrorFactory';
+import { Decimal } from "decimal.js";
+import { MultiType } from "../../typeSystem/multiType";
+import { ArrayType } from "../../typeSystem/array_type";
+import { Modes } from "../modes";
+import { StoreValue } from "../store/value/store_value";
+import { ProcessorErrorFactory } from "../error/processorErrorFactory";
 
 /**
  * sin
@@ -22,48 +22,57 @@ import { ProcessorErrorFactory } from '../error/processorErrorFactory';
  * min
  */
 
-function convertToRadians (degrees) {
+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.get().mod(360);
-     let result = null;
-     if(angle.eq(90)) {
-       result = new Decimal(1);
-     } else if (angle.eq(180)) {
+export function createSinFun() {
+  const sinFun = (sto, _) => {
+    const x = sto.applyStore("x");
+    const angle = x.get().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));
-     }
-     const temp = new StoreValue(Types.REAL, result);
-     sto.insertStore("$", temp);
-     sto.mode = Modes.RETURN;
-     return Promise.resolve(sto);
-   };
+    } else if (angle.eq(270)) {
+      result = new Decimal(-1);
+    } else {
+      result = Decimal.sin(convertToRadians(angle));
+    }
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
+    sto.mode = Modes.RETURN;
+    return Promise.resolve(sto);
+  };
 
-  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);
+  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 () {
+export function createCosFun() {
   const cosFun = (sto, _) => {
-    const x = sto.applyStore('x');
+    const x = sto.applyStore("x");
     const angle = x.get().mod(360);
     let result = null;
-    if(angle.eq(90)) {
+    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 = new Decimal(0);
     }
     result = Decimal.cos(convertToRadians(angle));
     const temp = new StoreValue(Types.REAL, result);
@@ -72,19 +81,33 @@ export function createCosFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 = function (sto, _) {
-    const x = sto.applyStore('x');
+export function createTanFun() {
+  const tanFun = function(sto, _) {
+    const x = sto.applyStore("x");
     const angle = x.get().mod(360);
-    if(angle.eq(90) || angle.eq(270)) {
-      return Promise.reject(ProcessorErrorFactory.undefined_tanget_value(x.get().toNumber(), this.function_call_stack.pop()));
+    if (angle.eq(90) || angle.eq(270)) {
+      return Promise.reject(
+        ProcessorErrorFactory.undefined_tanget_value(
+          x.get().toNumber(),
+          this.function_call_stack.pop()
+        )
+      );
     }
     const result = Decimal.tan(convertToRadians(angle));
     const temp = new StoreValue(Types.REAL, result);
@@ -93,18 +116,31 @@ export function createTanFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 = function (sto, _) {
-    const x = sto.applyStore('x');
-    if(x.get().isNeg()) {
-      return Promise.reject(ProcessorErrorFactory.negative_sqrt_value(this.function_call_stack.pop()));
+export function createSqrtFun() {
+  const sqrtFun = function(sto, _) {
+    const x = sto.applyStore("x");
+    if (x.get().isNeg()) {
+      return Promise.reject(
+        ProcessorErrorFactory.negative_sqrt_value(
+          this.function_call_stack.pop()
+        )
+      );
     }
     const result = x.get().sqrt();
     const temp = new StoreValue(Types.REAL, result);
@@ -113,17 +149,26 @@ export function createSqrtFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 () {
+export function createPowFun() {
   const powFun = (sto, _) => {
-    const x = sto.applyStore('x');
-    const y = sto.applyStore('y');
+    const x = sto.applyStore("x");
+    const y = sto.applyStore("y");
     const result = x.get().pow(y.get());
     const temp = new StoreValue(Types.REAL, result);
     sto.insertStore("$", temp);
@@ -131,19 +176,34 @@ export function createPowFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 = function (sto, _) {
-    const x = sto.applyStore('x');
+export function createLogFun() {
+  const logFun = function(sto, _) {
+    const x = sto.applyStore("x");
     if (x.get().isNegative()) {
-      return Promise.reject(ProcessorErrorFactory.negative_log_value(this.function_call_stack.pop()));
+      return Promise.reject(
+        ProcessorErrorFactory.negative_log_value(this.function_call_stack.pop())
+      );
     }
     const result = Decimal.log10(x.get());
     const temp = new StoreValue(Types.REAL, result);
@@ -152,16 +212,25 @@ export function createLogFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 () {
+export function createAbsFun() {
   const absFun = (sto, _) => {
-    const x = sto.applyStore('x');
+    const x = sto.applyStore("x");
     const result = x.get().abs();
     const temp = new StoreValue(x.type, result);
     sto.insertStore("$", temp);
@@ -169,16 +238,25 @@ export function createAbsFun () {
     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;
+  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 () {
+export function createNegateFun() {
   const negateFun = (sto, _) => {
-    const x = sto.applyStore('x');
+    const x = sto.applyStore("x");
     const result = x.get().negated();
     const temp = new StoreValue(x.type, result);
     sto.insertStore("$", temp);
@@ -186,16 +264,28 @@ export function createNegateFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 () {
+export function createInvertFun() {
   const invertFun = (sto, _) => {
-    const x = sto.applyStore('x');
+    const x = sto.applyStore("x");
     const result = toReal(1).dividedBy(x.get());
     const temp = new StoreValue(Types.REAL, result);
     sto.insertStore("$", temp);
@@ -203,16 +293,28 @@ export function createInvertFun () {
     return Promise.resolve(sto);
   };
 
- 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;
+  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 () {
+export function createMaxFun() {
   const maxFun = (sto, _) => {
-    const x = sto.applyStore('x');
+    const x = sto.applyStore("x");
     const numbers = x.get().map(sto_addrs => sto_addrs.get());
     const result = Decimal.max(...numbers);
     const temp = new StoreValue(x.type.innerType, result);
@@ -220,17 +322,23 @@ export function createMaxFun () {
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto);
   };
- const paramType = new ArrayType(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;
+  const paramType = new ArrayType(
+    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 () {
+export function createMinFun() {
   const minFun = (sto, _) => {
-    const x = sto.applyStore('x');
+    const x = sto.applyStore("x");
     const numbers = x.get().map(sto_addrs => sto_addrs.get());
     const result = Decimal.min(...numbers);
     const temp = new StoreValue(x.type.innerType, result);
@@ -238,23 +346,54 @@ export function createMinFun () {
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto);
   };
- const paramType = new ArrayType(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;
+  const paramType = new ArrayType(
+    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;
 }
 
-export function createRandFun () {
+let seed = Date.now();
+export function createRandFun() {
+  const a = 16807;
+  const m = 2147483647;
+  const c = 12345;
   const randFun = (sto, _) => {
-    const val = Math.random();
+    seed = (a * seed + c) % m;
+    const val = seed / (m - 1);
     const temp = new StoreValue(Types.REAL, new Decimal(val));
     sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto);
   };
-  const block = new Commands.CommandBlock([],  [new Commands.SysCall(randFun)]);
-  const func = new Commands.Function('$rand', Types.REAL, [], block);
+  const block = new Commands.CommandBlock([], [new Commands.SysCall(randFun)]);
+  const func = new Commands.Function("$rand", Types.REAL, [], block);
+  return func;
+}
+
+export function createSetSeedFun() {
+  const setSeedFun = (sto, _) => {
+    const value = sto.applyStore("x");
+    seed = value.get().toNumber();
+    sto.mode = Modes.RETURN;
+    return Promise.resolve(sto);
+  };
+  const block = new Commands.CommandBlock(
+    [],
+    [new Commands.SysCall(setSeedFun)]
+  );
+  const func = new Commands.Function(
+    "$setSeed",
+    Types.VOID,
+    [new Commands.FormalParameter(Types.INTEGER, "x", false)],
+    block
+  );
   return func;
 }