Ejemplo n.º 1
0
    def run(self, xrange="log", diff="relative"):
        r"""
        Compare accuracy of different methods for computing f.

        *xrange* is::

            log:    [10^-3,10^5]
            logq:   [10^-4, 10^1]
            linear: [1,1000]
            zoom:   [1000,1010]
            neg:    [-100,100]

        *diff* is "relative", "absolute" or "none"

        *x_bits* is the precision with which the x values are specified.  The
        default 23 should reproduce the equivalent of a single precisio
        """
        linear = not xrange.startswith("log")
        if xrange == "zoom":
            lin_min, lin_max, lin_steps = 1000, 1010, 2000
        elif xrange == "neg":
            lin_min, lin_max, lin_steps = -100.1, 100.1, 2000
        elif xrange == "linear":
            lin_min, lin_max, lin_steps = 1, 1000, 2000
            lin_min, lin_max, lin_steps = 0.001, 2, 2000
        elif xrange == "log":
            log_min, log_max, log_steps = -3, 5, 400
        elif xrange == "logq":
            log_min, log_max, log_steps = -4, 1, 400
        else:
            raise ValueError("unknown range "+xrange)
        with mp.workprec(500):
            # Note: we make sure that we are comparing apples to apples...
            # The x points are set using single precision so that we are
            # examining the accuracy of the transformation from x to f(x)
            # rather than x to f(nearest(x)) where nearest(x) is the nearest
            # value to x in the given precision.
            if linear:
                lin_min = max(lin_min, self.limits[0])
                lin_max = min(lin_max, self.limits[1])
                qrf = np.linspace(lin_min, lin_max, lin_steps, dtype='single')
                #qrf = np.linspace(lin_min, lin_max, lin_steps, dtype='double')
                qr = [mp.mpf(float(v)) for v in qrf]
                #qr = mp.linspace(lin_min, lin_max, lin_steps)
            else:
                log_min = np.log10(max(10**log_min, self.limits[0]))
                log_max = np.log10(min(10**log_max, self.limits[1]))
                qrf = np.logspace(log_min, log_max, log_steps, dtype='single')
                #qrf = np.logspace(log_min, log_max, log_steps, dtype='double')
                qr = [mp.mpf(float(v)) for v in qrf]
                #qr = [10**v for v in mp.linspace(log_min, log_max, log_steps)]

        target = self.call_mpmath(qr, bits=500)
        pylab.subplot(121)
        self.compare(qr, 'single', target, linear, diff)
        pylab.legend(loc='best')
        pylab.subplot(122)
        self.compare(qr, 'double', target, linear, diff)
        pylab.legend(loc='best')
        pylab.suptitle(self.name + " compared to 500-bit mpmath")
Ejemplo n.º 2
0
def ieee_eval(x):
    """
    Return the string representation of a floating point value in each prec.
    """
    x = mpf(x)
    sreps = list()
    for prec in ieee_formats:
        with mp.workprec(prec):
            sreps.append(str(x))
    return sreps
Ejemplo n.º 3
0
def workfloat(bytes_or_bits):
    ok = False
    bytes_or_bits = int(bytes_or_bits)
    for fmt in ieee_formats.values():
        if bytes_or_bits in (fmt.bits, fmt.bits // 8):
            ok = True
            with mp.workprec(fmt.prec):
                yield
    if not ok:
        raise KeyError(bytes_or_bits)
Ejemplo n.º 4
0
    def dist(self, f1, f2):
        """
        Return the distance between two values in ULPs.
        """
        with mp.workprec(self.prec):
            lo = mpf(min(f1, f2))
            hi = mpf(max(f1, f2))
            dist = 0
            while lo != hi:
                lo += self.ulp(lo)
                dist += 1

            return dist
Ejemplo n.º 5
0
    def ulp(self, x):
        """
        Return the unit of least precision for a value x.

        This is the floating point value which represents the delta between
        x and the closest representible number.
        """
        from .util import zero, one, two
        x = mpf(x)
        n = 0

        min_exp = abs(self.min_exp(denorm=True))
        with mp.workprec(self.prec):
            ulp = next_power(x)
            while (x + ulp) != x and ulp != zero and n < min_exp:
                ulp /= two
                n += 1

        return ulp * two
Ejemplo n.º 6
0
 def call_mpmath(self, vec, bits=500):
     """
     Direct calculation using mpmath extended precision library.
     """
     with mp.workprec(bits):
         return [self.mp_function(mp.mpf(x)) for x in vec]
Ejemplo n.º 7
0
def mp_fn(vec, bits=500):
    """
    Direct calculation using sympy multiprecision library.
    """
    with mp.workprec(bits):
        return [_mp_fn(mp.mpf(x)) for x in vec]