Ejemplo n.º 1
0
def IEEEContext(bitwidth):
    """
    Return IEEE 754-2008 context for a given bit width.

    The IEEE 754 standard specifies binary interchange formats with bitwidths
    16, 32, 64, 128, and all multiples of 32 greater than 128.  This function
    returns the context corresponding to the interchange format for the given
    bitwidth.

    See section 3.6 of IEEE 754-2008 or the bigfloat source for more details.

    """
    try:
        precision = {16: 11, 32: 24, 64: 53, 128: 113}[bitwidth]
    except KeyError:
        if not (bitwidth >= 128 and bitwidth % 32 == 0):
            raise ValueError("nonstandard bitwidth: bitwidth should be "
                             "16, 32, 64, 128, or k*32 for some k >= 4")

        with DefaultContext + Context(emin=-1, subnormalize=True):
            # log2(bitwidth), rounded to the nearest quarter
            l = log2(bitwidth)
        precision = 13 + bitwidth - int(4 * l)

    emax = 1 << bitwidth - precision - 1
    return Context(
        precision=precision,
        emin=4 - emax - precision,
        emax=emax,
        subnormalize=True,
    )
Ejemplo n.º 2
0
    def test_hashable(self):
        # create equal but non-identical contexts
        c1 = Context(emin=-999,
                     emax=999,
                     precision=100,
                     subnormalize=True,
                     rounding=mpfr.MPFR_RNDU)
        c2 = (Context(emax=999, emin=-999, rounding=mpfr.MPFR_RNDU) +
              Context(precision=100, subnormalize=True))
        self.assertEqual(hash(c1), hash(c2))
        self.assertEqual(c1, c2)
        self.assertIs(c1 == c2, True)
        self.assertIs(c1 != c2, False)

        # distinct contexts
        d1 = Context(emin=-999,
                     emax=999,
                     precision=100,
                     subnormalize=True,
                     rounding=mpfr.MPFR_RNDU)
        d2 = Context(emin=-999,
                     emax=999,
                     precision=101,
                     subnormalize=True,
                     rounding=mpfr.MPFR_RNDU)
        self.assertIs(d1 != d2, True)
        self.assertIs(d1 == d2, False)
Ejemplo n.º 3
0
    def test_with(self):
        # check use of contexts in with statements
        c = Context(
            emin=-123,
            emax=456,
            precision=1729,
            subnormalize=True,
            rounding=ROUND_TOWARD_POSITIVE,
        )
        d = Context(
            emin=0,
            emax=10585,
            precision=20,
            subnormalize=False,
            rounding=ROUND_TOWARD_NEGATIVE,
        )

        with c:
            # check nested with
            with d:
                self.assertEqual(getcontext().precision, d.precision)
                self.assertEqual(getcontext().emin, d.emin)
                self.assertEqual(getcontext().emax, d.emax)
                self.assertEqual(getcontext().subnormalize, d.subnormalize)
                self.assertEqual(getcontext().rounding, d.rounding)

            # check context is restored on normal exit
            self.assertEqual(getcontext().precision, c.precision)
            self.assertEqual(getcontext().emin, c.emin)
            self.assertEqual(getcontext().emax, c.emax)
            self.assertEqual(getcontext().subnormalize, c.subnormalize)
            self.assertEqual(getcontext().rounding, c.rounding)

            # check context is restored on abnormal exit, and that exceptions
            # raised within the with block are propagated
            try:
                with d:
                    raise ValueError
            except ValueError:
                pass
            else:
                self.fail("ValueError not propagated from with block")

            self.assertEqual(getcontext().precision, c.precision)
            self.assertEqual(getcontext().emin, c.emin)
            self.assertEqual(getcontext().emax, c.emax)
            self.assertEqual(getcontext().subnormalize, c.subnormalize)
            self.assertEqual(getcontext().rounding, c.rounding)
Ejemplo n.º 4
0
 def test_attributes(self):
     c = Context(
         emin=-999,
         emax=999,
         precision=100,
         subnormalize=True,
         rounding=ROUND_TIES_TO_EVEN,
     )
     self.assertIsInstance(c.precision, int)
     self.assertIsInstance(c.emax, int)
     self.assertIsInstance(c.emin, int)
     self.assertIsInstance(c.subnormalize, bool)
     self.assertIn(c.rounding, all_rounding_modes)
Ejemplo n.º 5
0
def IEEEContext(bitwidth):
    """
    Return IEEE 754-2008 context for a given bit width.

    The IEEE 754 standard specifies binary interchange formats with bitwidths
    16, 32, 64, 128, and all multiples of 32 greater than 128.  This function
    returns the context corresponding to the interchange format for the given
    bitwidth.

    See section 3.6 of IEEE 754-2008 or the bigfloat source for more details.

    """
    try:
        precision = {16: 11, 32: 24, 64: 53, 128: 113}[bitwidth]
    except KeyError:
        if not (bitwidth >= 128 and bitwidth % 32 == 0):
            raise ValueError(
                "nonstandard bitwidth: bitwidth should be "
                "16, 32, 64, 128, or k*32 for some k >= 4"
            )
        # The formula for the precision involves rounding 4*log2(width) to the
        # nearest integer. We have:
        #
        #   round(4*log2(width)) == round(log2(width**8)/2)
        #                        == floor((log2(width**8) + 1)/2)
        #                        == (width**8).bit_length() // 2
        #
        # (Note that 8*log2(width) can never be an odd integer, so we
        # don't care which way half-way cases round in the 'round'
        # operation.)
        precision = bitwidth - _bit_length(bitwidth ** 8) // 2 + 13

    emax = 1 << bitwidth - precision - 1
    return Context(
        precision=precision,
        emin=4 - emax - precision,
        emax=emax,
        subnormalize=True,
    )
Ejemplo n.º 6
0
 def test_bad_rounding_mode(self):
     with self.assertRaises(ValueError):
         Context(rounding=-1)
Ejemplo n.º 7
0
    def test_rounding_contexts(self):
        with RoundTiesToEven:
            self.assertEqual(getcontext().rounding, ROUND_TIES_TO_EVEN)
        with RoundTowardPositive:
            self.assertEqual(getcontext().rounding, ROUND_TOWARD_POSITIVE)
        with RoundTowardNegative:
            self.assertEqual(getcontext().rounding, ROUND_TOWARD_NEGATIVE)
        with RoundTiesToEven:
            self.assertEqual(getcontext().rounding, ROUND_TIES_TO_EVEN)
        with RoundAwayFromZero:
            self.assertEqual(getcontext().rounding, ROUND_AWAY_FROM_ZERO)

        # Rounding contexts should not affect existing settings for
        # precision, exponents, etc.
        original_contexts = [
            Context(
                precision=234,
                emin=-9999,
                emax=9999,
                subnormalize=True,
                rounding=ROUND_TOWARD_NEGATIVE,
            ),
            Context(
                precision=5,
                emin=-10,
                emax=10,
                subnormalize=False,
                rounding=ROUND_AWAY_FROM_ZERO,
            ),
        ]
        rounding_contexts = [
            RoundTiesToEven,
            RoundTowardPositive,
            RoundTowardNegative,
            RoundTowardZero,
            RoundAwayFromZero,
        ]

        for original_context in original_contexts:
            for rounding_context in rounding_contexts:
                with original_context:
                    with rounding_context:
                        self.assertEqual(
                            getcontext().precision,
                            original_context.precision,
                        )
                        self.assertEqual(
                            getcontext().emin,
                            original_context.emin,
                        )
                        self.assertEqual(
                            getcontext().emax,
                            original_context.emax,
                        )
                        self.assertEqual(
                            getcontext().subnormalize,
                            original_context.subnormalize,
                        )
                        self.assertEqual(
                            getcontext().rounding,
                            rounding_context.rounding,
                        )