I see documentation about integer overflow (it's causes a crash, or you can use special operators like &+.
What's the deal with Float? It seems that sometimes you get infinity, and sometimes you get the maximum value, so you can get a + 1 == a. Is this defined and documented somewhere?
let a = Float.greatestFiniteMagnitude
let b = a + 1.0
print("\(a), \(b), \(a == b)") // shows a and b are the same
let c = a * 1.0000001
print("\(c), \(a == c)") // inf, false
The arithmetic behavior of Float (and any type conforming to the FloatingPoint protocol) is fully defined by the IEEE 754 standard. This binding is documented in the documentation text for the protocols:
/// Adds two values and produces their sum, rounded to a
/// representable value.
///
/// The addition operator (`+`) calculates the sum of its two arguments. For
/// example:
///
/// let x = 1.5
/// let y = x + 2.25
/// // y == 3.75
///
/// The `+` operator implements the addition operation defined by the
/// [IEEE 754 specification][spec].
///
/// [spec]: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933
///
/// - Parameters:
/// - lhs: The first value to add.
/// - rhs: The second value to add.
override static func +(lhs: Self, rhs: Self) -> Self
IEEE 754 basic arithmetic operations (like + and *) are defined to be correctly rounded. You interpret the input values as exact real numbers, compute the result of the operation on the reals, and then round that result to the closest representable floating-point value. There's a special rule at the limit of the floating-point number line, where infinity is treated as though it were the next value, if the exponent range were unbounded.
Let's work through your examples:
let a = Float.greatestFiniteMagnitude
// a has the value 2^128 - 2^104
let b = a + 1.0
// the exact result of a + 1 (as a real number is):
// 2^128 - 2^104 + 1
// that's not representable as Float, so we have to round it.
// The closest finite value is a itself, and for the purposes of
// rounding, we treat the next large value, infinity, as though
// it were 2^128. a + 1 is much closer to a than it is to this
// value, so the result is a.
let c = a * 1.0000001
// First, 1.0000001 is actually 1.00000011920928955078125,
// or 1 + 2^(-23), since that's the closest representable value.
// When we multiply that by a in exact real arithmetic, we get:
//
// (2^128 - 2^104)(1 + 2^(-23)) = 2^128 + 2^105 - 2^104 - 2^81
// = 2^128 + 2^104 - 2^81
//
// Remember that, for the purposes of detecting overflow, we
// pretend that infinity is `2^128` (what would otherwise be the
// next representable value after `.greatestFiniteMagnitude).
// Since this value is bigger than that (and hence definitely
// bigger than the halfway point between a and that value), the
// computation overflow and returns +infinity.