90 lines
1.6 KiB
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)
|
|
}
|