Bitwise operations on floats (i am evil)
This commit is contained in:
parent
9e07d10c52
commit
2d58afe627
108
calculate.go
108
calculate.go
@ -12,6 +12,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
solution += subSolution
|
solution += subSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeSubtract:
|
case OpcodeSubtract:
|
||||||
if len(operation.operands) == 1 {
|
if len(operation.operands) == 1 {
|
||||||
solution, err = operation.operands[0].Solution()
|
solution, err = operation.operands[0].Solution()
|
||||||
@ -29,6 +30,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution -= subSolution
|
solution -= subSolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeMultiply:
|
case OpcodeMultiply:
|
||||||
solution = 1
|
solution = 1
|
||||||
for _, operand := range operation.operands {
|
for _, operand := range operation.operands {
|
||||||
@ -36,6 +38,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
solution *= subSolution
|
solution *= subSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeDivide:
|
case OpcodeDivide:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
@ -48,6 +51,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution /= subSolution
|
solution /= subSolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodePower:
|
case OpcodePower:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
@ -58,6 +62,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution = integerPower(solution, subSolution)
|
solution = integerPower(solution, subSolution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeRoot:
|
case OpcodeRoot:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
@ -69,6 +74,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution, subSolution)
|
solution, subSolution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeModulo:
|
case OpcodeModulo:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
@ -83,12 +89,14 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeOr:
|
case OpcodeOr:
|
||||||
for _, operand := range operation.operands {
|
for _, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
solution |= subSolution
|
solution |= subSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeNot:
|
case OpcodeNot:
|
||||||
if len(operation.operands) != 1 {
|
if len(operation.operands) != 1 {
|
||||||
err = ErrorWrongOperandCount
|
err = ErrorWrongOperandCount
|
||||||
@ -97,6 +105,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
|
|
||||||
subSolution, err = operation.operands[0].Solution()
|
subSolution, err = operation.operands[0].Solution()
|
||||||
solution = ^subSolution
|
solution = ^subSolution
|
||||||
|
|
||||||
case OpcodeAnd:
|
case OpcodeAnd:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
@ -107,6 +116,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution &= subSolution
|
solution &= subSolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeXor:
|
case OpcodeXor:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.Solution()
|
subSolution, err = operand.Solution()
|
||||||
@ -117,6 +127,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution ^= subSolution
|
solution ^= subSolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeLeftShift:
|
case OpcodeLeftShift:
|
||||||
if len(operation.operands) != 2 {
|
if len(operation.operands) != 2 {
|
||||||
err = ErrorWrongOperandCount
|
err = ErrorWrongOperandCount
|
||||||
@ -135,6 +146,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
solution = left << right
|
solution = left << right
|
||||||
|
|
||||||
case OpcodeRightShift:
|
case OpcodeRightShift:
|
||||||
if len(operation.operands) != 2 {
|
if len(operation.operands) != 2 {
|
||||||
err = ErrorWrongOperandCount
|
err = ErrorWrongOperandCount
|
||||||
@ -153,6 +165,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
solution = left >> right
|
solution = left >> right
|
||||||
|
|
||||||
case OpcodeMean:
|
case OpcodeMean:
|
||||||
if len(operation.operands) == 0 { break }
|
if len(operation.operands) == 0 { break }
|
||||||
for _, operand := range operation.operands {
|
for _, operand := range operation.operands {
|
||||||
@ -161,6 +174,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
solution += subSolution
|
solution += subSolution
|
||||||
}
|
}
|
||||||
solution /= int64(len(operation.operands))
|
solution /= int64(len(operation.operands))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = ErrorUnknownOpcode
|
err = ErrorUnknownOpcode
|
||||||
}
|
}
|
||||||
@ -169,6 +183,7 @@ func (operation *Operation) solution () (solution int64, err error) {
|
|||||||
|
|
||||||
func (operation *Operation) inexactSolution () (solution float64, err error) {
|
func (operation *Operation) inexactSolution () (solution float64, err error) {
|
||||||
var subSolution float64
|
var subSolution float64
|
||||||
|
var rawSolution uint64
|
||||||
|
|
||||||
switch operation.opcode {
|
switch operation.opcode {
|
||||||
case OpcodeAdd:
|
case OpcodeAdd:
|
||||||
@ -177,6 +192,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
solution += subSolution
|
solution += subSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeSubtract:
|
case OpcodeSubtract:
|
||||||
if len(operation.operands) == 1 {
|
if len(operation.operands) == 1 {
|
||||||
solution, err = operation.operands[0].InexactSolution()
|
solution, err = operation.operands[0].InexactSolution()
|
||||||
@ -194,6 +210,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
solution -= subSolution
|
solution -= subSolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeMultiply:
|
case OpcodeMultiply:
|
||||||
solution = 1
|
solution = 1
|
||||||
for _, operand := range operation.operands {
|
for _, operand := range operation.operands {
|
||||||
@ -201,6 +218,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
solution *= subSolution
|
solution *= subSolution
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeDivide:
|
case OpcodeDivide:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.InexactSolution()
|
subSolution, err = operand.InexactSolution()
|
||||||
@ -213,6 +231,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
solution /= subSolution
|
solution /= subSolution
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodePower:
|
case OpcodePower:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.InexactSolution()
|
subSolution, err = operand.InexactSolution()
|
||||||
@ -223,6 +242,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
solution = math.Pow(solution, subSolution)
|
solution = math.Pow(solution, subSolution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeRoot:
|
case OpcodeRoot:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.InexactSolution()
|
subSolution, err = operand.InexactSolution()
|
||||||
@ -233,6 +253,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
solution = math.Pow(solution, 1 / subSolution)
|
solution = math.Pow(solution, 1 / subSolution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpcodeModulo:
|
case OpcodeModulo:
|
||||||
for index, operand := range operation.operands {
|
for index, operand := range operation.operands {
|
||||||
subSolution, err = operand.InexactSolution()
|
subSolution, err = operand.InexactSolution()
|
||||||
@ -249,11 +270,89 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case
|
|
||||||
OpcodeOr, OpcodeNot, OpcodeAnd, OpcodeXor, OpcodeLeftShift,
|
case OpcodeOr:
|
||||||
OpcodeRightShift:
|
for _, operand := range operation.operands {
|
||||||
|
subSolution, err = operand.InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
rawSolution |= math.Float64bits(subSolution)
|
||||||
|
}
|
||||||
|
solution = math.Float64frombits(rawSolution)
|
||||||
|
|
||||||
err = ErrorWrongType
|
case OpcodeNot:
|
||||||
|
if len(operation.operands) != 1 {
|
||||||
|
err = ErrorWrongOperandCount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subSolution, err = operation.operands[0].InexactSolution()
|
||||||
|
solution = math.Float64frombits(^math.Float64bits(subSolution))
|
||||||
|
|
||||||
|
case OpcodeAnd:
|
||||||
|
for index, operand := range operation.operands {
|
||||||
|
subSolution, err = operand.InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
if index == 0 {
|
||||||
|
rawSolution = math.Float64bits(subSolution)
|
||||||
|
} else {
|
||||||
|
rawSolution &= math.Float64bits(subSolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
solution = math.Float64frombits(rawSolution)
|
||||||
|
|
||||||
|
case OpcodeXor:
|
||||||
|
for index, operand := range operation.operands {
|
||||||
|
subSolution, err = operand.InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
if index == 0 {
|
||||||
|
rawSolution = math.Float64bits(subSolution)
|
||||||
|
} else {
|
||||||
|
rawSolution ^= math.Float64bits(subSolution)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
solution = math.Float64frombits(rawSolution)
|
||||||
|
|
||||||
|
case OpcodeLeftShift:
|
||||||
|
if len(operation.operands) != 2 {
|
||||||
|
err = ErrorWrongOperandCount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var left, right float64
|
||||||
|
left, err = operation.operands[0].InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
right, err = operation.operands[1].InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
if right < 0 {
|
||||||
|
err = ErrorNegativeShiftAmount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
solution = math.Float64frombits (
|
||||||
|
math.Float64bits(left) <<
|
||||||
|
math.Float64bits(right))
|
||||||
|
|
||||||
|
case OpcodeRightShift:
|
||||||
|
if len(operation.operands) != 2 {
|
||||||
|
err = ErrorWrongOperandCount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var left, right float64
|
||||||
|
left, err = operation.operands[0].InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
right, err = operation.operands[1].InexactSolution()
|
||||||
|
if err != nil { return }
|
||||||
|
|
||||||
|
if right < 0 {
|
||||||
|
err = ErrorNegativeShiftAmount
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
solution = math.Float64frombits (
|
||||||
|
math.Float64bits(left) >>
|
||||||
|
math.Float64bits(right))
|
||||||
|
|
||||||
case OpcodeMean:
|
case OpcodeMean:
|
||||||
if len(operation.operands) == 0 { break }
|
if len(operation.operands) == 0 { break }
|
||||||
@ -263,6 +362,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
|
|||||||
solution += subSolution
|
solution += subSolution
|
||||||
}
|
}
|
||||||
solution /= float64(len(operation.operands))
|
solution /= float64(len(operation.operands))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = ErrorUnknownOpcode
|
err = ErrorUnknownOpcode
|
||||||
}
|
}
|
||||||
|
46
draw.go
46
draw.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
import "math"
|
||||||
import "git.tebibyte.media/sashakoshka/stone"
|
import "git.tebibyte.media/sashakoshka/stone"
|
||||||
|
|
||||||
func clear (x, y, width, height int) {
|
func clear (x, y, width, height int) {
|
||||||
@ -70,7 +71,7 @@ func drawNumberReadouts () {
|
|||||||
|
|
||||||
indicatorY := height - 12
|
indicatorY := height - 12
|
||||||
application.SetDot(0, indicatorY)
|
application.SetDot(0, indicatorY)
|
||||||
fmt.Fprint(application, "sel fin")
|
fmt.Fprint(application, "sel fin | int float")
|
||||||
fillColor(0, indicatorY, 10, 1, stone.ColorDim)
|
fillColor(0, indicatorY, 10, 1, stone.ColorDim)
|
||||||
|
|
||||||
if showEndResult {
|
if showEndResult {
|
||||||
@ -80,7 +81,19 @@ func drawNumberReadouts () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear(0, height - 10, 25, 10)
|
clear(0, height - 10, 25, 10)
|
||||||
|
|
||||||
|
if showFloat {
|
||||||
|
fillColor(14, indicatorY, 3, 1, stone.ColorBlue)
|
||||||
|
drawNumberReadoutsFloat()
|
||||||
|
} else {
|
||||||
|
fillColor(10, indicatorY, 3, 1, stone.ColorBlue)
|
||||||
|
drawNumberReadoutsInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawNumberReadoutsInt () {
|
||||||
|
_, height := application.Size()
|
||||||
|
|
||||||
var number int64
|
var number int64
|
||||||
var err error
|
var err error
|
||||||
if showEndResult {
|
if showEndResult {
|
||||||
@ -104,6 +117,35 @@ func drawNumberReadouts () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func drawNumberReadoutsFloat () {
|
||||||
|
_, height := application.Size()
|
||||||
|
|
||||||
|
var number float64
|
||||||
|
var err error
|
||||||
|
if showEndResult {
|
||||||
|
if expressionRoot != nil {
|
||||||
|
number, err = expressionRoot.InexactSolution()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if selectedExpression != nil {
|
||||||
|
number, err = selectedExpression.InexactSolution()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
application.SetDot((25 - len(err.Error())) / 2, height - 6)
|
||||||
|
fmt.Fprint(application, err.Error())
|
||||||
|
} else {
|
||||||
|
// TODO: display floats in these radixes. ignore the whole
|
||||||
|
// signs thing. floats are always signed so we need to always
|
||||||
|
// display a sign.
|
||||||
|
// drawHexadecimal (0, height - 10, uint64(number))
|
||||||
|
// drawDecimal (0, height - 8, uint64(number))
|
||||||
|
// drawOctal (0, height - 6, uint64(number))
|
||||||
|
drawBinary (0, height - 4, math.Float64bits(number))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func drawBinary (xOffset, yOffset int, number uint64) {
|
func drawBinary (xOffset, yOffset int, number uint64) {
|
||||||
bitOffset := 64
|
bitOffset := 64
|
||||||
|
|
||||||
|
1
main.go
1
main.go
@ -17,6 +17,7 @@ var inputBuffer stone.DamageBuffer
|
|||||||
var showLeftColumn bool
|
var showLeftColumn bool
|
||||||
var showEndResult bool = true
|
var showEndResult bool = true
|
||||||
var showSigned bool = true
|
var showSigned bool = true
|
||||||
|
var showFloat bool
|
||||||
|
|
||||||
func main () {
|
func main () {
|
||||||
application.SetTitle("MathPan")
|
application.SetTitle("MathPan")
|
||||||
|
Loading…
Reference in New Issue
Block a user