You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hal/hal_test.go

232 lines
5.1 KiB

4 years ago
package main
import (
"git.jfdev.de/JonasFranzDEV/hal/hal"
"git.jfdev.de/JonasFranzDEV/hal/parser"
"github.com/stretchr/testify/assert"
"math"
4 years ago
"testing"
)
func TestAddition(t *testing.T) {
input := []string{
"1 START",
"2 IN 0",
"3 STORE 10",
"4 IN 0",
"5 ADD 10",
"6 OUT 1",
"7 STOP",
}
program, err := parser.ParseProgram(input)
assert.NoError(t, err)
module, err := hal.NewHALModule(program, 256, 2, false)
assert.NoError(t, err)
4 years ago
module.IO[0] = hal.NewMockIO(10, 10)
outputMock := hal.NewMockIO()
module.IO[1] = outputMock
4 years ago
err = module.Run()
assert.NoError(t, err)
4 years ago
assert.Equal(t, float64(20), outputMock.Outputs[0])
4 years ago
}
func TestMax(t *testing.T) {
input := []string{
"00 IN 0",
"01 STORE 1",
4 years ago
"02 IN 0",
4 years ago
"03 STORE 2",
"04 SUB 1",
"05 JUMPPOS 9",
"06 LOAD 1",
"07 OUT 1",
"08 STOP",
"09 LOAD 2",
"10 OUT 1",
"11 STOP",
}
program, err := parser.ParseProgram(input)
assert.NoError(t, err)
module, err := hal.NewHALModule(program, 256, 2, false)
assert.NoError(t, err)
4 years ago
module.IO[0] = hal.NewMockIO(10, 15)
outputMock := hal.NewMockIO()
module.IO[1] = outputMock
4 years ago
err = module.Run()
assert.NoError(t, err)
4 years ago
assert.Len(t, outputMock.Outputs, 1)
assert.Equal(t, float64(15), outputMock.Outputs[0])
4 years ago
}
func TestNewton1(t *testing.T) {
input := []string{
"01 START",
"02 LOADNUM 1",
"03 STORE 10",
"10 MUL 10",
"11 MUL 10",
"12 STORE 12",
"13 MUL 10",
"14 MUL 10",
"15 STORE 11",
"21 LOAD 12",
"22 MULNUM 5",
"30 ADD 11",
"31 SUBNUM 5",
"32 STORE 20",
"33 SUB 50",
"34 JUMPNULL 66",
"35 LOAD 20",
"36 STORE 50",
"40 LOAD 10",
"41 MUL 10",
"42 STORE 21",
"43 MUL 10",
"44 MUL 10",
"45 MULNUM 5",
"46 STORE 22",
"47 LOAD 21",
"48 MULNUM 15",
"49 ADD 22",
"50 STORE 30",
"60 LOAD 20",
"61 DIV 30",
"62 STORE 40",
"63 LOAD 10",
"64 SUB 40",
"65 JUMP 03",
"66 LOAD 10",
4 years ago
"67 OUT 0",
"68 STOP",
}
program, err := parser.ParseProgram(input)
assert.NoError(t, err)
4 years ago
module, err := hal.NewHALModule(program, 256, 1, false)
assert.NoError(t, err)
4 years ago
outputMock := hal.NewMockIO()
module.IO[0] = outputMock
err = module.Run()
assert.NoError(t, err)
calculateNewton := func(start float64) float64 {
f1 := func(x float64) float64 {
return math.Pow(x, 5) + 5*math.Pow(x, 3) - 5
}
f1derived := func(x float64) float64 {
return 5*math.Pow(x, 4) + 15*math.Pow(x, 2)
}
var last float64
x := start
for x != last {
last = x
x = x - f1(x)/f1derived(x)
}
return x
}
4 years ago
4 years ago
assert.Equal(t, calculateNewton(1), outputMock.Outputs[0])
}
func TestNewton2(t *testing.T) {
input := []string{
"01 START",
"02 LOADNUM 1",
"03 STORE 10", // Every x is saved to reg 10
// f(x)
"10 MUL 10", // x²
"11 STORE 11", // Save x² to reg 11 for later use since we need that in the second part of the function
"12 MUL 10", // x³
"13 MUL 10", // x⁴
"14 MUL 10", // x⁵
"15 STORE 20", // This is x⁵ which we save here to save a few instructions
"16 MUL 10", // x⁶
"17 MULNUM 8", // x⁶ * 8
"18 STORE 12", // Reg 12 now contains the result of the first part of f(x)
"19 LOAD 11", // Put x² from earlier back in the accumulator
"20 MULNUM 3", // x² * 3
"21 ADD 12", // Add the first and second part of the function together, basically 8x⁶ + 3x²
"22 SUBNUM 3", // (8x⁶ + 3x²) - 3
"23 STORE 15", // Result in reg 15
// f'(x)
"30 LOAD 20", // x⁵ which we saved earlier while calculating x⁶
"31 MULNUM 48", // x⁵ * 48
"32 STORE 21", // Store the result in 21
"33 LOAD 10", // Load our x
"34 MULNUM 6", // x * 6
"35 ADD 21", // (x * 6) + 48x⁵
"36 STORE 25", // Store the result, which is the total result of f'(x) in reg 25
// x - f(x) / f'(x)
"40 LOAD 15", // load f(x)
"41 DIV 25", // f(x) / f'(x)
"42 MULNUM -1", // Invert the result
"43 ADD 10", // Add x: Because we inverted the result before, we can do this instead of SUB - lets us reuse the content of the accumulator
"44 STORE 35", // Reg 35 now contains the end result of x - f(x) / f'(x)
// This is our exit condition:
// We compare the current result with the last calculated result, if both are equal, we exit
"50 SUB 50", // Reg 50 contains the last result
"51 JUMPNULL 60", // If both are equal, we exit
"52 LOAD 35", // Otherwise load reg 15 again, store it as the current last result and continue
"53 STORE 50",
// Go to the beginning
"54 JUMP 03",
"60 LOAD 10", // Load the result
4 years ago
"61 OUT 0", // Print it
"62 STOP",
}
program, err := parser.ParseProgram(input)
assert.NoError(t, err)
4 years ago
module, err := hal.NewHALModule(program, 256, 1, false)
assert.NoError(t, err)
4 years ago
outputMock := hal.NewMockIO()
module.IO[0] = outputMock
err = module.Run()
assert.NoError(t, err)
calculateNewton := func(start float64) float64 {
f1 := func(x float64) float64 {
return 8*math.Pow(x, 6) + 3*math.Pow(x, 2) - 3
}
f1derived := func(x float64) float64 {
return 48*math.Pow(x, 5) + 6*x
}
var last float64
x := start
for x != last {
last = x
x = x - f1(x)/f1derived(x)
}
return x
}
4 years ago
assert.Equal(t, calculateNewton(1), outputMock.Outputs[0])
}