softfloat64/add.go

90 lines
1.6 KiB
Go

package softfloat64
import (
"math"
)
func Add(a, b float64, mode RoundingMode) float64 {
uA := math.Float64bits(a)
uB := math.Float64bits(b)
signA := sign(uA)
signB := sign(uB)
if signA == signB {
return addMags(uA, uB, signA, mode)
} else {
return subMags(uA, uB, signA, mode)
}
}
func addMags(a, b uint64, signZ bool, mode RoundingMode) float64 {
expA := exp(a)
sigA := frac(a)
expB := exp(b)
sigB := frac(b)
var expZ int16
var sigZ uint64
expDiff := expA - expB
// Same exponent
if expDiff == 0 {
if expA == 0 {
return math.Float64frombits(a + sigB)
}
if expA == 0x7FF {
if (sigA | sigB) != 0 {
return math.Float64frombits(propagateNaN(a, b))
}
return math.Float64frombits(a)
}
expZ = expA
sigZ = 0x0020000000000000 + sigA + sigB
sigZ <<= 9
} else {
sigA <<= 9
sigB <<= 9
if expDiff < 0 {
if expB == expnan64 {
if sigB != 0 {
return math.Float64frombits(propagateNaN(a, b))
}
return math.Float64frombits(pack(signZ, expnan64, 0))
}
expZ = expB
if expA != 0 {
sigA += 0x2000000000000000
} else {
sigA <<= 1
}
sigA = shiftRightJam(sigA, uint32(-expDiff))
} else {
if expA == expnan64 {
if sigA != 0 {
return math.Float64frombits(propagateNaN(a, b))
}
return math.Float64frombits(a)
}
expZ = expA
if expB != 0 {
sigB += 0x2000000000000000
} else {
sigB <<= 1
}
sigB = shiftRightJam(sigB, uint32(expDiff))
}
sigZ = 0x2000000000000000 + sigA + sigB
if sigZ < 0x4000000000000000 {
expZ--
sigZ <<= 1
}
}
return roundPack(signZ, expZ, sigZ, mode)
}