Bitwise operations on floats (i am evil)
This commit is contained in:
108
calculate.go
108
calculate.go
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user