Instance Property (Default implementation)swift-numerics 1.0.3RealModule

reciprocal

The (approximate) reciprocal (multiplicative inverse) of this number, if it is representable.

Real.swift:150
var reciprocal: Self? { get }

If x if finite and nonzero, and 1/x overflows or underflows, then x.reciprocal is nil. Otherwise, a.reciprocal is 1/x.

If x.reciprocal is non-nil, you may be able to replace division by x with multiplication by this value. It is not advantageous to do this for an isolated division unless it is a compile-time constant visible to the compiler, but if you are dividing many values by a single denominator, this will often be a significant performance win.

A typical use case looks something like this:

func divide<T: Real>(data: [T], by divisor: T) -> [T] {
  // If divisor is well-scaled, multiply by reciprocal.
  if let recip = divisor.reciprocal {
    return data.map { $0 * recip }
  }
  // Fallback on using division.
  return data.map { $0 / divisor }
}

Error Bounds:

Multiplying by the reciprocal instead of dividing will slightly perturb results. For example 5.0 / 3 is 1.6666666666666667, but 5.0 * 3.reciprocal! is 1.6666666666666665.

The error of a normal division is bounded by half an ulp of the result; we can derive a quick error bound for multiplication by the real reciprocal (when it exists) as follows (I will use circle operators to denote real-number arithmetic, and normal operators for floating-point arithmetic):

  a * b.reciprocal! = a * (1/b)
                    = a * (1  b)(1 + δ₁)
                    = (a  b)(1 + δ₁)(1 + δ₂)
                    = (a  b)(1 + δ₁ + δ₂ + δ₁δ₂)

where 0 < δᵢ <= ulpOfOne/2. This gives a roughly 1-ulp error, about twice the error bound we get using division. For most purposes this is an acceptable error, but if you need to match results obtained using division, you should not use this.