Bitwise operations on floats (i am evil)

This commit is contained in:
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
}