spire.math

fpf

package fpf

Visibility
  1. Public
  2. All

Type Members

  1. final class FPFilter[A] extends AnyRef

    A Floating Point Filter [1] provides a Numeric type that wraps another Numeric type, but defers its computation, instead providing a floating point (Double) approximation.

    A Floating Point Filter [1] provides a Numeric type that wraps another Numeric type, but defers its computation, instead providing a floating point (Double) approximation. For some operations, like signum, comparisons, equality checks, toFloat, etc, the Double approximation may be used to compute the result, rather than having to compute the exact value.

    An FPFilter can generally be used with any Ring numeric type (also supports EuclideanRing, Field, and Exponential). However, it should be kept in mind that FPFilter knows nothing about the type its wrapping and assumes that, generally, it is more accurate than it is. When an FPFilter cannot determine an answer to some predicate exactly, it will defer to the wrapped value, so it probably doesn't make sense to wrap Ints, when an Int will overflow before a Double!

    Good candidates to wrap in FPFilter are BigInts, Rationals, and BigDecimals. Note that Algebraic uses an FPFilter internally and thus nothing is gained by wrapping it. The reasoning behind this is that FPFilters add quite a bit of space requirements, as they may hold onto the entire expression tree (as call-by-name paramters), and, since Algebraic also does this by design, the asymptotic space requirements remain the same.

    Currently, the only way to operate on an FPFilter is by using its various numeric typeclasses.

    Note: Don't use FPFilters in hash maps. Getting the hashCode will always force the evaluation of value.

    [1] Burnikel, Funke, Seel. Exact Geometric Computation Using Cascading. SoCG 1998.

  2. trait FPFilterWrapper[A] extends AnyRef

    A typeclass approach to wrapping numeric types in an FPFilter.

    A typeclass approach to wrapping numeric types in an FPFilter. This way was chosen, as not all conversions are lossy, so we want to be able to capture those lossless conversions (Int, Float, Double, some BigInts and Longs, etc.), while still handling the generic case that is lossy.

  3. final class MaybeDouble extends AnyRef

    A MaybeDouble will hold a Double approximation so long as the Double's sign can be computed exactly.

    A MaybeDouble will hold a Double approximation so long as the Double's sign can be computed exactly. It is not a general number type, but is meant to be used in tandem with a more accurate, but slow (computationally), number type. When performing comparisons then, this can be checked first to save on potentially slow computation.

    For this type, if a method returns an Optional value, then that indicates that if None is returned, the answer cannot be computed exactly, but if Some(x) is returned, then that is guaranteed to be correct. For example, toLong, toFloat, sign, isWhole, etc. return these types of optional, only-if-correct, type values.

    Most likely you would not use this directly, but just wrap your number type in a FPFilter which maintains a MaybeDouble and handles all the lazy computation of the more accurate number type for you.

Value Members

  1. object FPFilter extends LowPriorityFPFilterImplicits with LowPriorityFPFilterWrappers

  2. object FPFilterWrapper extends LowPriorityFPFilterWrappers

    TODO: genericFPFilter is constantly being chosen over the ones defined here.

    TODO: genericFPFilter is constantly being chosen over the ones defined here. Does prioritized implicit selection work differently here for some odd reason? What the heck...

  3. object FastMaybeFloat

    A Long encoded version of MaybeDouble, geared for unboxed speed.

    A Long encoded version of MaybeDouble, geared for unboxed speed. This is significantly less accurate, but may provide good speed gains in common cases.

    The values approx and measure are both truncated floats with the full 8 bit exponent, but only 16 bit mantissa. Since the measure is always positive, we only need 2 * (16 + 8) + 1 = 49 bits for these 2 numbers, which leaves 15 bits for the index. These sizes were chosen so that worst case relative error, ind * eps, has a value less than 1. In our case, with worst case ind = -1 >>> 17, we have ind * eps =~ 0.5.

    This was inspired by Erik Osheim's awesome FastComplex, which encodes the imaginary and real parts as 2 Floats in the a single Long.

    TODO: Perhaps, if we've only used + or *, we could store a higher precision float instead, since we don't need measure. Use 1 bit to handle the switching, taken from the index.

  4. object MaybeDouble

Ungrouped