Bitwise operations on floats (i am evil)

This commit is contained in:
Sasha Koshka 2022-11-23 10:57:49 -05:00
parent 9e07d10c52
commit 2d58afe627
3 changed files with 149 additions and 6 deletions

View File

@ -12,6 +12,7 @@ func (operation *Operation) solution () (solution int64, err error) {
if err != nil { return }
solution += subSolution
}
case OpcodeSubtract:
if len(operation.operands) == 1 {
solution, err = operation.operands[0].Solution()
@ -29,6 +30,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution -= subSolution
}
}
case OpcodeMultiply:
solution = 1
for _, operand := range operation.operands {
@ -36,6 +38,7 @@ func (operation *Operation) solution () (solution int64, err error) {
if err != nil { return }
solution *= subSolution
}
case OpcodeDivide:
for index, operand := range operation.operands {
subSolution, err = operand.Solution()
@ -48,6 +51,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution /= subSolution
}
}
case OpcodePower:
for index, operand := range operation.operands {
subSolution, err = operand.Solution()
@ -58,6 +62,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution = integerPower(solution, subSolution)
}
}
case OpcodeRoot:
for index, operand := range operation.operands {
subSolution, err = operand.Solution()
@ -69,6 +74,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution, subSolution)
}
}
case OpcodeModulo:
for index, operand := range operation.operands {
subSolution, err = operand.Solution()
@ -83,12 +89,14 @@ func (operation *Operation) solution () (solution int64, err error) {
}
}
}
case OpcodeOr:
for _, operand := range operation.operands {
subSolution, err = operand.Solution()
if err != nil { return }
solution |= subSolution
}
case OpcodeNot:
if len(operation.operands) != 1 {
err = ErrorWrongOperandCount
@ -97,6 +105,7 @@ func (operation *Operation) solution () (solution int64, err error) {
subSolution, err = operation.operands[0].Solution()
solution = ^subSolution
case OpcodeAnd:
for index, operand := range operation.operands {
subSolution, err = operand.Solution()
@ -107,6 +116,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution &= subSolution
}
}
case OpcodeXor:
for index, operand := range operation.operands {
subSolution, err = operand.Solution()
@ -117,6 +127,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution ^= subSolution
}
}
case OpcodeLeftShift:
if len(operation.operands) != 2 {
err = ErrorWrongOperandCount
@ -135,6 +146,7 @@ func (operation *Operation) solution () (solution int64, err error) {
}
solution = left << right
case OpcodeRightShift:
if len(operation.operands) != 2 {
err = ErrorWrongOperandCount
@ -153,6 +165,7 @@ func (operation *Operation) solution () (solution int64, err error) {
}
solution = left >> right
case OpcodeMean:
if len(operation.operands) == 0 { break }
for _, operand := range operation.operands {
@ -161,6 +174,7 @@ func (operation *Operation) solution () (solution int64, err error) {
solution += subSolution
}
solution /= int64(len(operation.operands))
default:
err = ErrorUnknownOpcode
}
@ -169,6 +183,7 @@ func (operation *Operation) solution () (solution int64, err error) {
func (operation *Operation) inexactSolution () (solution float64, err error) {
var subSolution float64
var rawSolution uint64
switch operation.opcode {
case OpcodeAdd:
@ -177,6 +192,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
if err != nil { return }
solution += subSolution
}
case OpcodeSubtract:
if len(operation.operands) == 1 {
solution, err = operation.operands[0].InexactSolution()
@ -194,6 +210,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
solution -= subSolution
}
}
case OpcodeMultiply:
solution = 1
for _, operand := range operation.operands {
@ -201,6 +218,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
if err != nil { return }
solution *= subSolution
}
case OpcodeDivide:
for index, operand := range operation.operands {
subSolution, err = operand.InexactSolution()
@ -213,6 +231,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
solution /= subSolution
}
}
case OpcodePower:
for index, operand := range operation.operands {
subSolution, err = operand.InexactSolution()
@ -223,6 +242,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
solution = math.Pow(solution, subSolution)
}
}
case OpcodeRoot:
for index, operand := range operation.operands {
subSolution, err = operand.InexactSolution()
@ -233,6 +253,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
solution = math.Pow(solution, 1 / subSolution)
}
}
case OpcodeModulo:
for index, operand := range operation.operands {
subSolution, err = operand.InexactSolution()
@ -249,11 +270,89 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
}
}
}
case
OpcodeOr, OpcodeNot, OpcodeAnd, OpcodeXor, OpcodeLeftShift,
OpcodeRightShift:
case OpcodeOr:
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:
if len(operation.operands) == 0 { break }
@ -263,6 +362,7 @@ func (operation *Operation) inexactSolution () (solution float64, err error) {
solution += subSolution
}
solution /= float64(len(operation.operands))
default:
err = ErrorUnknownOpcode
}

46
draw.go
View File

@ -1,6 +1,7 @@
package main
import "fmt"
import "math"
import "git.tebibyte.media/sashakoshka/stone"
func clear (x, y, width, height int) {
@ -70,7 +71,7 @@ func drawNumberReadouts () {
indicatorY := height - 12
application.SetDot(0, indicatorY)
fmt.Fprint(application, "sel fin")
fmt.Fprint(application, "sel fin | int float")
fillColor(0, indicatorY, 10, 1, stone.ColorDim)
if showEndResult {
@ -80,7 +81,19 @@ func drawNumberReadouts () {
}
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 err error
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) {
bitOffset := 64

View File

@ -17,6 +17,7 @@ var inputBuffer stone.DamageBuffer
var showLeftColumn bool
var showEndResult bool = true
var showSigned bool = true
var showFloat bool
func main () {
application.SetTitle("MathPan")