-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
352 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* eslint-disable @typescript-eslint/prefer-readonly */ | ||
// The SOR (Re)actor | ||
import { Reactor, State } from "../../core/internal"; | ||
|
||
export class SORActor extends Reactor { | ||
constructor( | ||
parent: Reactor, | ||
pos: number, | ||
_value: number, | ||
colour: number, | ||
nx: number, | ||
ny: number, | ||
omega: number, | ||
sorSource: Reactor, | ||
peer: boolean | ||
) { | ||
super(parent, "SORActor"); | ||
|
||
const x = Math.floor(pos / ny); | ||
const y = pos % ny; | ||
|
||
const omegaOverFour = 0.25 * omega; | ||
const oneMinusOmega = 1.0 - omega; | ||
|
||
const neighbours = (() => { | ||
const calPos = (x: number, y: number): number => (x * ny + y); | ||
|
||
if (x > 0 && x < nx - 1 && y > 0 && y < ny - 1) { | ||
return [calPos(x, y + 1), | ||
calPos(x + 1, y), | ||
calPos(x, y - 1), | ||
calPos(x - 1, y)]; | ||
} | ||
if ((x === 0 || x === (nx - 1)) && (y === 0 || y === (ny - 1))) { | ||
return [ | ||
(x === 0) ? calPos(x + 1, y) : calPos(x - 1, y), | ||
(y === 0) ? calPos(x, y + 1) : calPos(x, y - 1) | ||
]; | ||
} | ||
if ((x === 0 || x === (nx - 1)) || (y === 0 || y === (ny - 1))) { | ||
if (x === 0 || x === nx - 1) { | ||
return [ | ||
(x === 0) ? calPos(x + 1, y) : calPos(x - 1, y), | ||
calPos(x, y + 1), | ||
calPos(x, y - 1) | ||
]; | ||
} | ||
return [ | ||
(y === 0) ? calPos(x, y + 1) : calPos(x, y - 1), | ||
calPos(x+1, y), | ||
calPos(x-1, y) | ||
]; | ||
} | ||
return []; | ||
})(); | ||
} | ||
|
||
private iter = new State(0); | ||
private maxIter = new State(0); | ||
private msgRcv = new State(0); | ||
private sorActors = new State<Reactor[]>([]); | ||
|
||
protected | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Reactor, State } from "../../core/internal"; | ||
import { SORRunner } from "./runner"; | ||
import { SorBorder } from "./sorutils"; | ||
|
||
export class SORPeer extends Reactor { | ||
sorActors: State<Reactor[]>; | ||
constructor( | ||
parent: Reactor, | ||
s: number, | ||
partStart: number, | ||
matrixPart: number[][], | ||
border: SorBorder, | ||
sorSource: SORRunner | ||
) { | ||
super(parent, "SORPeer"); | ||
this.sorActors = new State([]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { InMultiPort, InPort, OutMultiPort, OutPort, Parameter, Reactor, State, } from "../../core/internal"; | ||
import { SORActor } from "./actor"; | ||
import { SORPeer } from "./peer"; | ||
import { Message, SorBorder, omega } from "./sorutils"; | ||
|
||
export class SORRunner extends Reactor { | ||
protected sorActors: State<Reactor[]>; | ||
protected sorPeer: State<Reactor | undefined>; | ||
|
||
protected portToSORActors: OutPort<Message>; | ||
protected portToSORPeer: OutPort<Message>; | ||
// Unsure if this would work, let's just try...... | ||
protected portFromSORActor: InPort<Message>; | ||
protected portFromSORPeer: InPort<Message>; | ||
|
||
constructor(parent: Reactor, size: number, _randoms: number[][]) { | ||
super(parent, "SORRunner"); | ||
// These are in SorRunner; | ||
const s = size; | ||
// In the scala implementation a simple /2 was used. | ||
// In JS we might need to enforce some sort of guarantee as it was used to calculate position | ||
const part = Math.floor(s / 2); | ||
/** These are from Savina. They should be rather irrelevant, actually. */ | ||
this.sorActors = new State([]); | ||
this.sorPeer = new State(undefined); | ||
|
||
/** These are the actual messaging passing mechanism that are synonomous to that of Savina. */ | ||
// This creates a bunch of ports. | ||
this.portToSORActors = new OutPort(this); | ||
this.portToSORPeer = new OutPort(this); | ||
|
||
// SorRunner::boot() | ||
this.addMutation( | ||
[this.startup], | ||
[this.sorActors, this.sorPeer], | ||
function (this, sorActors, sorPeer) { | ||
const myBorder: Reactor[] = []; | ||
const randoms = _randoms; | ||
|
||
// In scala, (i <- 0 until s) is loop excluding s. | ||
const sorActorsValue = sorActors.get(); | ||
for (let i = 0; i < s; ++i) { | ||
let c = i % 2; | ||
for (let j = 0; j < part; ++j) { | ||
const pos = i * (part + 1) + j; | ||
c = 1 - c; | ||
// We modify them in bulk, then update the state. | ||
// Unlike in Scala we do not need to initialise the array here, JS supports sparse array. | ||
// I have absolutely no idea why these parametres are called as such...... | ||
sorActorsValue[pos] = this.getReactor()._uncheckedAddSibling( | ||
SORActor, | ||
pos, randoms[i][j], c, s, part + 1, omega, this.getReactor(), false | ||
); | ||
// TODO: Make connections | ||
if (j === (part - 1)) { | ||
myBorder[i] = sorActorsValue[pos]; | ||
} | ||
|
||
} | ||
} | ||
sorActors.set(sorActorsValue); | ||
|
||
const partialMatrix: number[][] = []; | ||
for (let i = 0; i < s; ++i) { | ||
for (let j = 0; j < s - part; ++j) { | ||
partialMatrix[i][j] = randoms[i][j + part]; | ||
} | ||
} | ||
|
||
const sorPeerValue = this.getReactor()._uncheckedAddSibling( | ||
SORPeer, | ||
s, part, partialMatrix, new SorBorder(myBorder), | ||
// A dirty hack. Maybe this will be removed as ports get added. | ||
this.getReactor() as SORRunner | ||
); | ||
sorPeer.set(sorPeerValue); | ||
// TODO: Add connections. | ||
|
||
} | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { Reactor } from "../../core/reactor"; | ||
|
||
// Savina implementation of PRNG | ||
export class SavinaPRNG { | ||
private value: number; | ||
|
||
constructor(value?: number) { | ||
this.value = value ?? 1145141919; | ||
} | ||
|
||
public nextNumber(): number { | ||
this.value = ((this.value * 1309) + 13849) & 65535; | ||
return this.value; | ||
} | ||
|
||
public nextFloat(): number { | ||
return 1.0 / (this.nextNumber() + 1); | ||
} | ||
} | ||
|
||
// This is not a recommended way to use JS, but whatever...... | ||
|
||
export const refVal = [ | ||
0.000003189420084871275, | ||
0.001846644602759566, | ||
0.0032099996270638005, | ||
0.0050869220175413146, | ||
0.008496328291240363, | ||
0.016479973604143234, | ||
0.026575660248076397, | ||
// This is different from the Savina one because JS doesn't have high precision | ||
1.026575660248076, | ||
2.026575660248076, | ||
3.026575660248076 | ||
]; | ||
|
||
export const jacobi = 100; | ||
|
||
export const omega = 1.25; | ||
|
||
export function randomMatrix(m: number, n: number): number[][] { | ||
const mat = []; | ||
const prng = new SavinaPRNG(114514); | ||
for (let i = 0; i < m; ++i) { | ||
const row = []; | ||
for (let j = 0; j < n; ++j) { | ||
row.push(prng.nextFloat() * 1e-6); | ||
} | ||
mat.push(row); | ||
} | ||
return mat; | ||
} | ||
|
||
export function jgfValidate(gTotal: number, size: number): void { | ||
const dev = Math.abs(gTotal - refVal[size]); | ||
if (dev > 1.0e-12) { | ||
console.log("Validation failed"); | ||
console.log(`GTotal=${gTotal}; ${refVal[size]}; ${dev}; ${size}`); | ||
} else { | ||
console.log("Validation OK!"); | ||
} | ||
} | ||
|
||
export enum MessageTypes { | ||
sorBorderMessage, | ||
sorStartMessage, | ||
sorValueMessage, | ||
sorBootMessage, | ||
sorResuleMessage | ||
} | ||
|
||
export class SorBorder { | ||
borderActors: Reactor[]; | ||
constructor(borderActors: Reactor[]) { | ||
this.borderActors = borderActors; | ||
} | ||
} | ||
|
||
export interface Message { | ||
messageType: MessageTypes; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { | ||
type WritablePort, | ||
Parameter, | ||
InPort, | ||
OutPort, | ||
State, | ||
Action, | ||
Reactor, | ||
App, | ||
TimeValue, | ||
Origin, | ||
Log | ||
} from "../../core/internal"; | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { App, InPort, OutPort, Reactor } from "../../core/internal"; | ||
|
||
class Master extends Reactor { | ||
outp: OutPort<number>; | ||
|
||
constructor(parent: Reactor, receivers: Receiver[]) { | ||
super(parent, ""); | ||
this.outp = new OutPort(this); | ||
|
||
this.addMutation( | ||
[this.startup], | ||
[this.outp], | ||
function(this, outp) { | ||
let i = 0; | ||
for (const r of receivers) { | ||
console.log(`Master: triggering ${i}`) | ||
this.connect(outp, r.inp); | ||
this.getReactor().writable(outp).set(i++); | ||
this.disconnect(outp, r.inp); | ||
} | ||
} | ||
); | ||
} | ||
} | ||
|
||
class Receiver extends Reactor { | ||
inp: InPort<number>; | ||
outp: OutPort<number>; | ||
|
||
constructor(parent: Reactor, receiver2: Receiver2) { | ||
super(parent, ""); | ||
this.inp = new InPort(this); | ||
this.outp = new OutPort(this); | ||
|
||
this.addMutation( | ||
[this.inp], | ||
[this.inp, this.outp], | ||
function(this, inp, outp) { | ||
const message = inp.get(); | ||
if (message == null) { | ||
throw Error("Receiver: Message is null."); | ||
} | ||
console.log(`Receiver: message ${message}. Sending.`); | ||
this.connect(outp, receiver2.inp); | ||
this.getReactor().writable(outp).set(message); | ||
this.disconnect(outp, receiver2.inp); | ||
} | ||
); | ||
} | ||
} | ||
|
||
class Receiver2 extends Reactor { | ||
inp: InPort<number>; | ||
|
||
constructor(parent: Reactor) { | ||
super(parent, ""); | ||
this.inp = new InPort(this); | ||
|
||
this.addReaction( | ||
[this.inp], | ||
[this.inp], | ||
function (this, inp) { | ||
console.log(`Receiver2: received ${inp.get()}`) | ||
} | ||
); | ||
} | ||
} | ||
|
||
class Apppp extends App { | ||
master: Master; | ||
recvs: Receiver[]; | ||
recv2: Receiver2; | ||
|
||
constructor() { | ||
super(undefined, undefined, false, ()=>(undefined), ()=>(undefined), ""); | ||
this.recv2 = new Receiver2(this); | ||
this.recvs = []; | ||
for (let i = 0; i < 10; ++i) { | ||
this.recvs.push(new Receiver(this, this.recv2)); | ||
} | ||
this.master = new Master(this, this.recvs); | ||
} | ||
} | ||
|
||
const app = new Apppp(); | ||
app._start(); |