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) }