├── .gitignore
├── .travis.yml
├── MANIFEST.in
├── bigfloat
├── test
│ ├── test___all__.py
│ ├── test_data
│ │ ├── next_up.bft
│ │ ├── next_down.bft
│ │ ├── mod.bft
│ │ ├── pos.bft
│ │ ├── various.bft
│ │ └── floordiv.bft
│ ├── __init__.py
│ ├── test_rounding_mode.py
│ ├── test_mpz.py
│ ├── test_context.py
│ └── test_formatting.py
├── version.py
├── rounding_mode.py
├── ieee.py
├── formatting.py
├── __init__.py
├── mpfr_supplemental.py
└── context.py
├── Misc
├── mpfr_notes.txt
└── alg_notes.tex
├── cgmp.pxd
├── RELEASING.rst
├── INSTALL.rst
├── fabfile.py
├── examples
├── lanczos_coeffs.py
└── contfrac.py
├── docs
├── Makefile
└── source
│ ├── index.rst
│ ├── conf.py
│ └── tutorial
│ └── index.rst
├── README.rst
├── COPYING.LESSER
├── CHANGELOG.rst
├── setup.py
└── cmpfr.pxd
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled files.
2 | __pycache__/
3 | *.py[co]
4 |
5 | # Cython output.
6 | mpfr.c
7 | mpfr*.so
8 |
9 | # Build output (covers docs and extension build)
10 | build/
11 |
12 | # Distribution
13 | MANIFEST
14 | dist/
15 | bigfloat.egg-info/
16 |
17 | # Coverage output.
18 | .coverage
19 | htmlcov
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | dist: bionic
3 | python:
4 | - 2.7
5 | - 3.5
6 | - 3.6
7 | - 3.7
8 | - 3.8
9 | install:
10 | - sudo apt-get update
11 | - sudo apt-get install libmpfr-dev
12 | - pip install Cython
13 | - pip install six
14 | script:
15 | - python setup.py build_ext --inplace
16 | - python -m unittest discover -v
17 | notifications:
18 | email:
19 | - dickinsm@gmail.com
20 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include CHANGELOG.rst
2 | include COPYING
3 | include COPYING.LESSER
4 | include INSTALL.rst
5 | include MANIFEST.in
6 | include README.rst
7 |
8 | # Distribution should include Cython source files, though the generated
9 | # C file is included, so neither Cython nor the Cython source is
10 | # necessary for installation.
11 | include cgmp.pxd
12 | include cmpfr.pxd
13 | include mpfr.pyx
14 |
15 | # Explicitly include the generated C source.
16 | include mpfr.c
17 |
18 | # Include docs and examples directories in their entirety.
19 | graft docs
20 | graft examples
21 |
--------------------------------------------------------------------------------
/bigfloat/test/test___all__.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import unittest
3 |
4 |
5 | class TestAll(unittest.TestCase):
6 | def test_from_import_star_on_bigfloat_package(self):
7 | exec("from bigfloat import *")
8 |
9 | def test_duplicates(self):
10 | # Check for duplicate entries in __all__.
11 | from bigfloat import __all__
12 |
13 | counts = collections.defaultdict(int)
14 | for item in __all__:
15 | counts[item] += 1
16 | duplicates = sorted(k for k, v in counts.items() if v > 1)
17 | self.assertEqual(duplicates, [])
18 |
19 |
20 | if __name__ == "__main__":
21 | unittest.main()
22 |
--------------------------------------------------------------------------------
/bigfloat/test/test_data/next_up.bft:
--------------------------------------------------------------------------------
1 | context double_precision
2 |
3 | next_up -inf -> -1.fffffffffffffp+1023
4 | next_up -1p-1074 -> -0
5 | next_up -0.8p-1075 -> -0
6 | next_up -0.4p-1075 -> -0
7 | next_up -0.000000000000000000000000001p-1075 -> -0
8 | next_up -1p-999999999 -> -0
9 | next_up -0 -> 1p-1074
10 | next_up 0 -> 1p-1074
11 | next_up 1p-999999999 -> 1p-1074
12 | next_up 0.8p-1074 -> 1p-1074
13 | next_up 0.ffffffffffffffffffffp-1074 -> 1p-1074
14 | next_up 1p-1074 -> 2p-1074
15 | next_up 1p-1023 -> 1.0000000000002p-1023
16 | next_up 1p-1022 -> 1.0000000000001p-1022
17 | next_up 1.ffffffffffffep+1023 -> 1.fffffffffffffp+1023
18 | next_up 1.ffffffffffffeffffp+1023 -> 1.fffffffffffffp+1023
19 | next_up 1.fffffffffffffp+1023 -> inf
20 | next_up inf -> inf
21 |
22 | next_up nan -> nan
23 |
--------------------------------------------------------------------------------
/bigfloat/test/test_data/next_down.bft:
--------------------------------------------------------------------------------
1 | context double_precision
2 |
3 | next_down -inf -> -inf
4 | next_down -1.fffffffffffffp+1023 -> -inf
5 | next_down -1.ffffffffffffeffffp+1023 -> -1.fffffffffffffp+1023
6 | next_down -1.ffffffffffffep+1023 -> -1.fffffffffffffp+1023
7 | next_down -1p-1022 -> -1.0000000000001p-1022
8 | next_down -1p-1023 -> -1.0000000000002p-1023
9 | next_down -1p-1074 -> -2p-1074
10 | next_down -0.ffffffffffffffffffffp-1074 -> -1p-1074
11 | next_down -0.8p-1074 -> -1p-1074
12 | next_down -1p-999999999 -> -1p-1074
13 | next_down -0 -> -1p-1074
14 | next_down 0 -> -1p-1074
15 | next_down 1p-999999999 -> 0
16 | next_down 0.000000000000000000000000001p-1075 -> 0
17 | next_down 0.4p-1075 -> 0
18 | next_down 0.8p-1075 -> 0
19 | next_down 1p-1074 -> 0
20 | next_down inf -> 1.fffffffffffffp+1023
21 |
22 | next_down nan -> nan
23 |
--------------------------------------------------------------------------------
/bigfloat/test/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
--------------------------------------------------------------------------------
/bigfloat/version.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | major = 0
19 | minor = 5
20 | patch = 0
21 | prerelease = "dev"
22 |
23 | if prerelease:
24 | __version__ = "{}.{}.{}-{}".format(major, minor, patch, prerelease)
25 | else:
26 | __version__ = "{}.{}.{}".format(major, minor, patch)
27 |
28 | # Release and version for Sphinx purposes.
29 |
30 | # The short X.Y version.
31 | version = "{}.{}".format(major, minor)
32 |
33 | # The full version, including patchlevel and alpha/beta/rc tags.
34 | release = __version__
35 |
--------------------------------------------------------------------------------
/Misc/mpfr_notes.txt:
--------------------------------------------------------------------------------
1 | Notes on using MPFR
2 | -------------------
3 |
4 | 1. Should always have mpfr_emin <= mpfr_emax, else results may be undefined.
5 |
6 | For example, if mpfr_emin > mpfr_emax then the only representable
7 | values are zeros, infinities and nans. But then nextbelow(+Inf) should
8 | return 0.0. It doesn't (at least in MPFR 2.4.1.)
9 |
10 | Suggest adding a note to the docs saying that mpfr_emin <= mpfr_emax is
11 | required.
12 |
13 |
14 | 2. mpfr_set_ui_2exp doesn't check bounds on exponents; can induce
15 | undefined behaviour by taking exponent close to LONG_MAX.
16 |
17 | On my (32-bit) machine:
18 |
19 | mpfr_set_ui_2exp(x, 12345, LONG_MAX-10, RoundTiesToEven) gives
20 | 'Infinity' (correct), but a ternary value of 0 (incorrect);
21 | mpfr_set_ui_2exp(x, 12345, LONG_MAX-14, RoundTiesToEven) is okay.
22 | mpfr_set_ui_2exp(x, 12345, LONG_MAX-9, RoundTiesToEven) gives a result
23 | of 0 (bad) and ternary value of -1.
24 |
25 | (1st case gives the magic exponent corr. to infinity...)
26 |
27 | Should document a range of exponents for which mpfr_set_ui_2exp is
28 | guaranteed to work correcly.
29 |
30 | 3. mpfr_init_set, ... mpfr_init_set_f are macros. Please document this.
31 | (mpfr_init_set_str appears not to be a macro)
32 | XXX. It *is* documented!
33 |
34 | 4. Using set_emax and set_emin: the warning about making sure that all
35 | current variables are within the exponent bounds seems a little extreme (
36 | and in practice, unusable), but it appears to be true that some functions
37 | and operations (e.g., addition) assume that arguments are within bounds.
38 |
39 | The way to get around this seems to be to do all computations with
40 | unbounded exponent range, and then just set emax and emin before doing
41 | check_range.
42 |
--------------------------------------------------------------------------------
/cgmp.pxd:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | cdef extern from "gmp.h":
19 | # GMP type declarations
20 | ctypedef int mp_exp_t
21 | ctypedef unsigned int mp_limb_t
22 |
23 | ctypedef struct __mpz_struct:
24 | int _mp_alloc
25 | int _mp_size
26 | mp_limb_t *_mp_d
27 |
28 | # ctypedef __mpz_struct mpz_t[1]
29 | ctypedef __mpz_struct *mpz_ptr
30 |
31 | # 5.1 Initialization Functions
32 |
33 | void mpz_init(mpz_ptr x)
34 | void mpz_clear(mpz_ptr x)
35 |
36 | # 5.2 Assignment Functions
37 |
38 | int mpz_set_str(mpz_ptr rop, const char *str, int base)
39 |
40 | # 5.4 Conversion Functions
41 |
42 | char *mpz_get_str(char *str, int base, const mpz_ptr op)
43 |
44 | # 13 Custom Allocation
45 |
46 | void mp_get_memory_functions(
47 | void *(**alloc_func_ptr) (size_t),
48 | void *(**realloc_func_ptr) (void *, size_t, size_t),
49 | void (**free_func_ptr) (void *, size_t))
50 |
--------------------------------------------------------------------------------
/RELEASING.rst:
--------------------------------------------------------------------------------
1 | Preparing a release
2 | ===================
3 |
4 | Notes on creating a release. These notes apply my own system, currently OS X
5 | 10.9, with mpfr and gmp installed via MacPorts.
6 |
7 | 0. Make sure that you have a clean and up-to-date source tree.
8 |
9 | 1. Create a release branch::
10 |
11 | git checkout release/0.4.0
12 |
13 | 2. Update version numbers if necessary. Places that need to be updated
14 | include::
15 |
16 | docs/conf.py ('version' and 'release' keys)
17 | setup.py ('version')
18 |
19 | You might also look at:
20 |
21 | * ``CHANGELOG.rst``
22 | * ``INSTALL.rst``
23 | * ``RELEASING.rst`` (this document).
24 |
25 | 3. Create a test release with ``python setup.py sdist``; copy the generated
26 | tarball and check that it's possible to install from it. Run tests.
27 |
28 | 4. When satisfied, tag the release::
29 |
30 | git tag -a v0.4.0
31 |
32 | 5. Upload the release to PyPI. Register first if necessary::
33 |
34 | python setup.py sdist upload
35 |
36 | If you don't have PyPI details registered in ~/.pypirc, this may fail; in
37 | that case you'll need to reissue the 'python setup.py sdist upload' command
38 | in the form::
39 |
40 | python setup.py sdist register upload
41 |
42 | Make sure you answer "y" to the "Save your login (y/N)" prompt!
43 |
44 | 6. Update tags on ReadTheDocs.
45 |
46 | 7. Building docs to upload to PyPI. In the docs directory, do::
47 |
48 | make html
49 | cd build/html
50 | zip -r bigfloat_docs.zip *
51 | mv -i bigfloat_docs.zip ~/Desktop
52 |
53 | Now you can go to::
54 |
55 | http://pypi.python.org/pypi?%3Aaction=pkg_edit&name=bigfloat
56 |
57 | and upload the documentation from there. The documentation is uploaded
58 | to http://pythonhosted.org/bigfloat.
59 |
60 |
61 | Post-release
62 | ============
63 |
64 | 0. Merge the release branch back into master.
65 |
66 | 1. Bump version number again.
67 |
--------------------------------------------------------------------------------
/Misc/alg_notes.tex:
--------------------------------------------------------------------------------
1 | \documentclass{article}
2 |
3 | \usepackage{amsmath}
4 | \usepackage{amsthm}
5 |
6 | \newtheorem{lemma}{Lemma}
7 | \newtheorem{definition}{Definition}
8 | \newtheorem{examples}{Examples}
9 | \newcommand{\abs}[1]{|#1|}
10 |
11 | \begin{document}
12 |
13 | \begin{definition}
14 | For any positive real number~$x$, write $e(x)$ for the unique
15 | integer such that $2^{e(x)-1} \le x < 2^{e(x)}$.
16 | \end{definition}
17 |
18 | The following lemma is needed for implementing efficient floor division.
19 |
20 | \begin{lemma}
21 | Suppose that $x$, $y$ and $z$ are positive binary floating-point
22 | numbers with precisions~$p$, $q$ and $r$ respectively, and that $z
23 | \ne x/y$. Then
24 | $$\abs{z-x/y} \ge 2^{e(z) - \max(p+1,\,q+r)}$$ where $e(z)$ is the
25 | unique integer satisfying $2^{e(z)-1} \le z < 2^{e(z)}$.
26 | \end{lemma}
27 |
28 | \begin{proof}
29 | We divide the proof into two cases. For the first case, suppose
30 | that $e(x)-e(y) \ge e(z)-1$. Now
31 | $$z-x/y = (2^{r-e(z)}z)2^{e(z)-r} - \frac{2^{p-e(x)}x}{2^{q-e(y)}y}
32 | 2^{e(x)-e(y)-p+q}$$ and $2^{r-e(z)}z$, $2^{p-e(x)}x$ and
33 | $2^{q-e(y)}y$ are integers, so
34 | $$z-x/y = \left(\frac{2^{\min(e(z)-r,\,
35 | e(x)-e(y)-p+q)}}{2^{q-e(y)}y}\right)t$$ for some nonzero
36 | integer~$t$. Since $2^{-e(y)}y < 1$ by definition of $e(y)$, and
37 | $e(x)-e(y)\ge e(z)-1$ by assumption, the result follows.
38 |
39 | For the second case, suppose that $e(x) - e(y) \le e(z)-2$.
40 | Then
41 | \begin{align*}
42 | \frac xy&\le (1-2^{-p})2^{e(x)-e(y)+1}\\
43 | &\le(1-2^{-p})2^{e(z)-1}\\
44 | &< 2^{e(z)-1} \le z.
45 | \end{align*}
46 | and hence $z-x/y \ge 2^{e(z)-1-p}$. Hence we obtain the inequality
47 | of the theorem. We get equality if and only if $y$ and $z$ are
48 | exact powers of $2$, $x = (1-2^{-p})2^{e(x)}$, $e(x)-e(y) = e(z)-2$,
49 | and $p+1\ge q+r$.
50 | \end{proof}
51 |
52 | \begin{examples}
53 | Suppose that $y=z=1$, $x = 1-2^{-5}$. Then $e(z) = 1$,
54 | we can take $q=r=1$ and $p=5$, and the lemma predicts that $z-x/y \ge
55 | 2^{-5}$.
56 |
57 | Now suppose that
58 |
59 | \end{examples}
60 |
61 | \end{document}
62 |
--------------------------------------------------------------------------------
/bigfloat/rounding_mode.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | from mpfr import (
19 | MPFR_RNDN,
20 | MPFR_RNDZ,
21 | MPFR_RNDU,
22 | MPFR_RNDD,
23 | MPFR_RNDA,
24 | )
25 |
26 |
27 | __all__ = [
28 | "RoundingMode",
29 | "ROUND_TIES_TO_EVEN",
30 | "ROUND_TOWARD_ZERO",
31 | "ROUND_TOWARD_POSITIVE",
32 | "ROUND_TOWARD_NEGATIVE",
33 | "ROUND_AWAY_FROM_ZERO",
34 | ]
35 |
36 |
37 | _rounding_mode_names = {
38 | MPFR_RNDN: "ROUND_TIES_TO_EVEN",
39 | MPFR_RNDZ: "ROUND_TOWARD_ZERO",
40 | MPFR_RNDU: "ROUND_TOWARD_POSITIVE",
41 | MPFR_RNDD: "ROUND_TOWARD_NEGATIVE",
42 | MPFR_RNDA: "ROUND_AWAY_FROM_ZERO",
43 | }
44 |
45 |
46 | class RoundingMode(int):
47 | """ Subclass of int representing a rounding mode. """
48 |
49 | def __new__(cls, value):
50 | self = int.__new__(cls, value)
51 | if value not in _rounding_mode_names:
52 | raise ValueError("Invalid rounding mode {}".format(value))
53 | self._name = _rounding_mode_names[value]
54 | return self
55 |
56 | def __repr__(self):
57 | return self._name
58 |
59 | __str__ = __repr__
60 |
61 |
62 | ROUND_TIES_TO_EVEN = RoundingMode(MPFR_RNDN)
63 | ROUND_TOWARD_ZERO = RoundingMode(MPFR_RNDZ)
64 | ROUND_TOWARD_POSITIVE = RoundingMode(MPFR_RNDU)
65 | ROUND_TOWARD_NEGATIVE = RoundingMode(MPFR_RNDD)
66 | ROUND_AWAY_FROM_ZERO = RoundingMode(MPFR_RNDA)
67 |
--------------------------------------------------------------------------------
/INSTALL.rst:
--------------------------------------------------------------------------------
1 | Prerequisites
2 | -------------
3 |
4 | This package requires Python 2.7 or 3.5 or later. The `MPFR `_
5 | and `GMP `_ libraries will need to be already installed on your
6 | system, along with any necessary development headers for both of those
7 | libraries. On Linux, look for a package named something like ``libmpfr-dev``
8 | or ``mpfr-devel``, along with similarly named packages for GMP.
9 |
10 |
11 | Installation from a release tarball
12 | -----------------------------------
13 |
14 | The instructions cover installation from either a repository clone,
15 | or a source distribution tarball. After cloning the repository
16 | or unpacking the tarball, you should have a top-level directory
17 | named something like ``bigfloat-0.4.0``.
18 |
19 | (1) Enter that top-level directory and execute the command::
20 |
21 | python setup.py install
22 |
23 | For a site-wide installation, you many need to be become superuser, or use
24 | the ``sudo`` command. You can also build and install in two separate
25 | steps::
26 |
27 | python setup.py build_ext
28 | sudo python setup.py install
29 |
30 | For this to work, the MPFR and GMP libraries must already be installed
31 | on your system, complete with any necessary header files. If the libraries
32 | or include files are found in an unusual place, you many need to modify
33 | environment variables so that the setup command can find the necessary
34 | header files.
35 |
36 | An example: on OS X 10.9, using the system Python but with MPFR and GMP
37 | installed in /opt/local (e.g., by MacPorts), one can do::
38 |
39 | $ sudo LIBRARY_PATH=/opt/local/lib CPATH=/opt/local/include python setup.py install
40 |
41 | Alternatively, the include and library directories can be supplied to the
42 | build_ext command::
43 |
44 | $ python setup.py build_ext -I /opt/local/include -L/opt/local/lib
45 | $ sudo python setup.py install
46 |
47 | (2) (Optional) Test the installation by doing::
48 |
49 | $ python -m unittest discover bigfloat
50 |
51 | (3) To check that everything's working, compute the square root of 2 to 1000
52 | bits of precision::
53 |
54 | >>> from bigfloat import precision, sqrt
55 | >>> with precision(200):
56 | ... print(sqrt(2))
57 | ...
58 | 1.4142135623730950488016887242096980785696718753769480731766796
59 |
60 | If installation was successful, the ``bigfloat-0.4.0`` directory that you
61 | created can now be deleted.
62 |
63 |
64 | .. _gmp library: http://gmplib.org
65 | .. _mpfr library: http://www.mpfr.org
66 |
--------------------------------------------------------------------------------
/bigfloat/ieee.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | from bigfloat.core import _bit_length
19 | from bigfloat.context import Context
20 |
21 |
22 | def IEEEContext(bitwidth):
23 | """
24 | Return IEEE 754-2008 context for a given bit width.
25 |
26 | The IEEE 754 standard specifies binary interchange formats with bitwidths
27 | 16, 32, 64, 128, and all multiples of 32 greater than 128. This function
28 | returns the context corresponding to the interchange format for the given
29 | bitwidth.
30 |
31 | See section 3.6 of IEEE 754-2008 or the bigfloat source for more details.
32 |
33 | """
34 | try:
35 | precision = {16: 11, 32: 24, 64: 53, 128: 113}[bitwidth]
36 | except KeyError:
37 | if not (bitwidth >= 128 and bitwidth % 32 == 0):
38 | raise ValueError(
39 | "nonstandard bitwidth: bitwidth should be "
40 | "16, 32, 64, 128, or k*32 for some k >= 4"
41 | )
42 | # The formula for the precision involves rounding 4*log2(width) to the
43 | # nearest integer. We have:
44 | #
45 | # round(4*log2(width)) == round(log2(width**8)/2)
46 | # == floor((log2(width**8) + 1)/2)
47 | # == (width**8).bit_length() // 2
48 | #
49 | # (Note that 8*log2(width) can never be an odd integer, so we
50 | # don't care which way half-way cases round in the 'round'
51 | # operation.)
52 | precision = bitwidth - _bit_length(bitwidth ** 8) // 2 + 13
53 |
54 | emax = 1 << bitwidth - precision - 1
55 | return Context(
56 | precision=precision,
57 | emin=4 - emax - precision,
58 | emax=emax,
59 | subnormalize=True,
60 | )
61 |
62 |
63 | half_precision = IEEEContext(16)
64 | single_precision = IEEEContext(32)
65 | double_precision = IEEEContext(64)
66 | quadruple_precision = IEEEContext(128)
67 |
--------------------------------------------------------------------------------
/fabfile.py:
--------------------------------------------------------------------------------
1 | from fabric.api import local, lcd
2 |
3 | # Default choice for Python executable
4 | PYTHON = "python"
5 | COVERAGE = "coverage"
6 |
7 | # Paths for mpfr and gmp libraries and include files.
8 | LIBRARY_PATH = "/opt/local/lib"
9 | INCLUDE_PATH = "/opt/local/include"
10 |
11 |
12 | def build(python=PYTHON):
13 | """Build the bigfloat library for in-place testing."""
14 | clean()
15 | local(
16 | "LIBRARY_PATH={library_path} CPATH={include_path} {python} "
17 | "setup.py build_ext --inplace".format(
18 | library_path=LIBRARY_PATH,
19 | include_path=INCLUDE_PATH,
20 | python=python,
21 | )
22 | )
23 |
24 |
25 | def install(python=PYTHON):
26 | """Install into site-packages"""
27 | local(
28 | "LIBRARY_PATH={library_path} CPATH={include_path} {python} "
29 | "setup.py build".format(
30 | library_path=LIBRARY_PATH,
31 | include_path=INCLUDE_PATH,
32 | python=python,
33 | )
34 | )
35 | local("sudo {python} setup.py install".format(python=python))
36 |
37 |
38 | def uninstall(python=PYTHON):
39 | """Uninstall from site-packages"""
40 | site_packages = local(
41 | "{python} -c 'from distutils.sysconfig import "
42 | "get_python_lib; print(get_python_lib())'".format(python=python),
43 | capture=True,
44 | )
45 | with lcd(site_packages):
46 | local("sudo rm mpfr.so")
47 | local("sudo rm -fr bigfloat")
48 | local("sudo rm bigfloat*.egg-info")
49 |
50 |
51 | def clean():
52 | """Remove build artifacts."""
53 | local("git clean -fdX")
54 |
55 |
56 | def run_tests(python=PYTHON):
57 | unittest = "{python} -m unittest".format(python=python)
58 | local("{unittest} discover -v .".format(unittest=unittest))
59 |
60 |
61 | def test(python=PYTHON):
62 | """Run tests on a single version of Python."""
63 | build(python=python)
64 | run_tests(python=python)
65 |
66 |
67 | def coverage(coverage=COVERAGE):
68 | local("{coverage} run -m unittest discover -v .".format(coverage=coverage))
69 | local("{coverage} html".format(coverage=coverage))
70 |
71 |
72 | def html():
73 | """Build html documentation."""
74 | clean()
75 | with lcd("docs"):
76 | local("make html")
77 |
78 |
79 | def pdf():
80 | """Build PDF documentation."""
81 | clean()
82 | with lcd("docs"):
83 | local("make latexpdf")
84 |
85 |
86 | def docs(python=PYTHON):
87 | """Build PDF and html documentation."""
88 | html()
89 | pdf()
90 |
91 |
92 | def test_all():
93 | """Run tests on Python versions 2.7 and 3.5 through 3.8."""
94 | test(python="python2.7")
95 | test(python="python3.5")
96 | test(python="python3.6")
97 | test(python="python3.7")
98 | test(python="python3.8")
99 |
--------------------------------------------------------------------------------
/bigfloat/test/test_data/mod.bft:
--------------------------------------------------------------------------------
1 | context double_precision
2 | context RoundTiesToEven
3 |
4 | # Check treatment of signs in normal cases.
5 | mod 0x5p0 0x3p0 -> 0x2p0
6 | mod -0x5p0 0x3p0 -> 0x1p0
7 | mod 0x5p0 -0x3p0 -> -0x1p0
8 | mod -0x5p0 -0x3p0 -> -0x2p0
9 |
10 | # A result of zero should have the same sign
11 | # as the second argument.
12 | mod 0x2p0 0x1p0 -> 0x0p0
13 | mod -0x2p0 0x1p0 -> 0x0p0
14 | mod 0x2p0 -0x1p0 -> -0x0p0
15 | mod -0x2p0 -0x1p0 -> -0x0p0
16 |
17 | # Finite input cases where the result may not be exact.
18 | mod 0x1p-100 0x1p0 -> 0x1p-100
19 | mod -0x1p-100 0x1p0 -> 0x1p0 Inexact
20 | mod 0x1p-100 -0x1p0 -> -0x1p0 Inexact
21 | mod -0x1p-100 -0x1p0 -> -0x1p-100
22 |
23 | # NaN inputs
24 | mod nan nan -> nan NanFlag
25 | mod -inf nan -> nan NanFlag
26 | mod -0x1p0 nan -> nan NanFlag
27 | mod -0x0p0 nan -> nan NanFlag
28 | mod 0x0p0 nan -> nan NanFlag
29 | mod 0x1p0 nan -> nan NanFlag
30 | mod nan inf -> nan NanFlag
31 | mod nan -inf -> nan NanFlag
32 | mod nan -0x1p0 -> nan NanFlag
33 | mod nan -0x0p0 -> nan NanFlag
34 | mod nan 0x0p0 -> nan NanFlag
35 | mod nan 0x1p0 -> nan NanFlag
36 | mod nan inf -> nan NanFlag
37 |
38 | # Other invalid cases: x infinite, y zero.
39 | mod inf -inf -> nan NanFlag
40 | mod inf -0x1p0 -> nan NanFlag
41 | mod inf -0x0p0 -> nan NanFlag
42 | mod inf 0x0p0 -> nan NanFlag
43 | mod inf 0x1p0 -> nan NanFlag
44 | mod inf inf -> nan NanFlag
45 | mod -inf -inf -> nan NanFlag
46 | mod -inf -0x1p0 -> nan NanFlag
47 | mod -inf -0x0p0 -> nan NanFlag
48 | mod -inf 0x0p0 -> nan NanFlag
49 | mod -inf 0x1p0 -> nan NanFlag
50 | mod -inf inf -> nan NanFlag
51 | mod -inf 0x0p0 -> nan NanFlag
52 | mod -0x1p0 0x0p0 -> nan NanFlag
53 | mod -0x0p0 0x0p0 -> nan NanFlag
54 | mod 0x0p0 0x0p0 -> nan NanFlag
55 | mod 0x1p0 0x0p0 -> nan NanFlag
56 | mod inf 0x0p0 -> nan NanFlag
57 | mod -inf -0x0p0 -> nan NanFlag
58 | mod -0x1p0 -0x0p0 -> nan NanFlag
59 | mod -0x0p0 -0x0p0 -> nan NanFlag
60 | mod 0x0p0 -0x0p0 -> nan NanFlag
61 | mod 0x1p0 -0x0p0 -> nan NanFlag
62 | mod inf -0x0p0 -> nan NanFlag
63 |
64 | # x finite, y infinite.
65 | mod -0x1p0 inf -> inf
66 | mod -0x0p0 inf -> 0x0p0
67 | mod 0x0p0 inf -> 0x0p0
68 | mod 0x1p0 inf -> 0x1p0
69 |
70 | mod -0x1p0 -inf -> -0x1p0
71 | mod -0x0p0 -inf -> -0x0p0
72 | mod 0x0p0 -inf -> -0x0p0
73 | mod 0x1p0 -inf -> -inf
74 |
75 | # x zero, y finite but nonzero: sign of x is irrelevant.
76 | mod 0x0p0 0x5p0 -> 0x0p0
77 | mod -0x0p0 0x5p0 -> 0x0p0
78 | mod 0x0p0 -0x5p0 -> -0x0p0
79 | mod -0x0p0 -0x5p0 -> -0x0p0
80 |
--------------------------------------------------------------------------------
/bigfloat/test/test_rounding_mode.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | import unittest
19 |
20 | import mpfr as mpfr
21 | from bigfloat.rounding_mode import (
22 | RoundingMode,
23 | ROUND_TIES_TO_EVEN,
24 | ROUND_TOWARD_ZERO,
25 | ROUND_TOWARD_POSITIVE,
26 | ROUND_TOWARD_NEGATIVE,
27 | ROUND_AWAY_FROM_ZERO,
28 | )
29 |
30 |
31 | class TestRoundingMode(unittest.TestCase):
32 | def test_rounding_mode_from_int(self):
33 | rm = RoundingMode(mpfr.MPFR_RNDN)
34 | self.assertEqual(rm, ROUND_TIES_TO_EVEN)
35 | self.assertIsInstance(rm, RoundingMode)
36 |
37 | def test_rounding_mode_from_rounding_mode(self):
38 | rm = RoundingMode(ROUND_TOWARD_POSITIVE)
39 | self.assertEqual(rm, ROUND_TOWARD_POSITIVE)
40 | self.assertIsInstance(rm, RoundingMode)
41 |
42 | def test_str(self):
43 | self.assertEqual(str(ROUND_TIES_TO_EVEN), "ROUND_TIES_TO_EVEN")
44 | self.assertEqual(str(ROUND_TOWARD_ZERO), "ROUND_TOWARD_ZERO")
45 | self.assertEqual(str(ROUND_TOWARD_POSITIVE), "ROUND_TOWARD_POSITIVE")
46 | self.assertEqual(str(ROUND_TOWARD_NEGATIVE), "ROUND_TOWARD_NEGATIVE")
47 | self.assertEqual(str(ROUND_AWAY_FROM_ZERO), "ROUND_AWAY_FROM_ZERO")
48 |
49 | def test_repr(self):
50 | self.assertEqual(repr(ROUND_TIES_TO_EVEN), "ROUND_TIES_TO_EVEN")
51 | self.assertEqual(repr(ROUND_TOWARD_ZERO), "ROUND_TOWARD_ZERO")
52 | self.assertEqual(repr(ROUND_TOWARD_POSITIVE), "ROUND_TOWARD_POSITIVE")
53 | self.assertEqual(repr(ROUND_TOWARD_NEGATIVE), "ROUND_TOWARD_NEGATIVE")
54 | self.assertEqual(repr(ROUND_AWAY_FROM_ZERO), "ROUND_AWAY_FROM_ZERO")
55 |
56 | def test_int(self):
57 | self.assertEqual(int(ROUND_TIES_TO_EVEN), mpfr.MPFR_RNDN)
58 | self.assertEqual(int(ROUND_TOWARD_ZERO), mpfr.MPFR_RNDZ)
59 | self.assertEqual(int(ROUND_TOWARD_POSITIVE), mpfr.MPFR_RNDU)
60 | self.assertEqual(int(ROUND_TOWARD_NEGATIVE), mpfr.MPFR_RNDD)
61 | self.assertEqual(int(ROUND_AWAY_FROM_ZERO), mpfr.MPFR_RNDA)
62 |
63 | def test_type(self):
64 | self.assertTrue(issubclass(RoundingMode, int))
65 | self.assertIs(type(ROUND_TIES_TO_EVEN), RoundingMode)
66 | self.assertIs(type(ROUND_TOWARD_ZERO), RoundingMode)
67 | self.assertIs(type(ROUND_TOWARD_POSITIVE), RoundingMode)
68 | self.assertIs(type(ROUND_TOWARD_NEGATIVE), RoundingMode)
69 | self.assertIs(type(ROUND_AWAY_FROM_ZERO), RoundingMode)
70 |
71 | def test_invalid_rounding_mode(self):
72 | with self.assertRaises(ValueError):
73 | RoundingMode(-1)
74 |
75 |
76 | if __name__ == "__main__":
77 | unittest.main()
78 |
--------------------------------------------------------------------------------
/bigfloat/test/test_mpz.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | import unittest
19 |
20 | from mpfr import (
21 | Mpz_t,
22 | mpz_set_str,
23 | mpz_get_str,
24 | )
25 |
26 |
27 | class TestMpz(unittest.TestCase):
28 | def test_mpz_initial_value(self):
29 | z = Mpz_t()
30 | self.assertEqual(mpz_get_str(10, z), "0")
31 |
32 | def test_set_and_get_str(self):
33 | z = Mpz_t()
34 | mpz_set_str(z, "123", 10)
35 | self.assertEqual(mpz_get_str(10, z), "123")
36 |
37 | def test_set_str_base(self):
38 | z = Mpz_t()
39 |
40 | # Triples (str, base, value)
41 | test_values = [
42 | ("1001", 2, 9),
43 | ("1001", 3, 28),
44 | ("123", 10, 123),
45 | ("-123", 10, -123),
46 | ("abc", 16, 2748),
47 | ("ABC", 16, 2748),
48 | ("A", 37, 10),
49 | ("a", 37, 36),
50 | ("z", 62, 61),
51 | ("Z", 62, 35),
52 | ("11", 0, 11),
53 | ("011", 0, 9),
54 | ("0x12", 0, 18),
55 | ("-0x12", 0, -18),
56 | ("0X012", 0, 18),
57 | ("0B00101", 0, 5),
58 | ("-1 2 3 4 5 6", 0, -123456),
59 | ("\n3\t45\n6\n\n\n7\t\n", 0, 34567),
60 | ]
61 |
62 | for s, base, expected in test_values:
63 | mpz_set_str(z, s, base)
64 | actual = int(mpz_get_str(10, z))
65 | self.assertEqual(actual, expected)
66 |
67 | bad_bases = [-2, 1, 63]
68 | for base in bad_bases:
69 | with self.assertRaises(ValueError):
70 | mpz_set_str(z, "101", base)
71 |
72 | def test_set_str_bad_values(self):
73 | z = Mpz_t()
74 |
75 | bad_values = [
76 | ("123\nabc", 10),
77 | ("12", 2),
78 | ]
79 |
80 | for value, base in bad_values:
81 | mpz_set_str(z, str(-314159), 10)
82 | with self.assertRaises(ValueError):
83 | mpz_set_str(z, value, base)
84 | self.assertEqual(int(mpz_get_str(10, z)), -314159)
85 |
86 | def test_get_str(self):
87 | z = Mpz_t()
88 |
89 | # Triples (value, base, expected_output)
90 | test_values = [
91 | (456, 2, "111001000"),
92 | (456, 10, "456"),
93 | (456, 16, "1c8"),
94 | (456, 36, "co"),
95 | (456, 37, "CC"),
96 | (456, -2, "111001000"),
97 | (456, -16, "1C8"),
98 | (456, -36, "CO"),
99 | ]
100 |
101 | for value, base, expected in test_values:
102 | mpz_set_str(z, str(value), 10)
103 | actual = mpz_get_str(base, z)
104 | self.assertEqual(actual, expected)
105 |
106 | bad_bases = [-37, -1, 0, 1, 63]
107 |
108 | for base in bad_bases:
109 | with self.assertRaises(ValueError):
110 | mpz_get_str(base, z)
111 |
--------------------------------------------------------------------------------
/bigfloat/test/test_data/pos.bft:
--------------------------------------------------------------------------------
1 | context double_precision
2 | context RoundTiesToEven
3 |
4 | pos 0 -> 0
5 | pos -0 -> -0
6 | pos inf -> inf
7 | pos -inf -> -inf
8 | pos nan -> nan NanFlag
9 |
10 | # smallest representable positive value is 1p-1074
11 | # values in (0, 0.8p-1074] -> 0 Inexact Underflow
12 |
13 | # exactly representable with precision 53 and unbounded exponent,
14 | # but not exactly representable with precision 53 and bounded exponent
15 | pos 0.8p-1075 -> 0 Inexact Underflow
16 | pos 0.cp-1075 -> 0 Inexact Underflow
17 | pos 0.ffffffffffffp-1075 -> 0 Inexact Underflow
18 |
19 | # not exactly representable with precision 53 and unbounded exponent
20 | pos 0.ffffffffffffffffffffp-1075 -> 0 Inexact Underflow
21 | pos 1p-1075 -> 0 Inexact Underflow
22 |
23 | # values in (0.8p-1075, 1p-1074) -> 1p-1074 Inexact Underflow
24 |
25 | pos 1.00000000000000000001p-1075 -> 1p-1074 Inexact Underflow
26 | pos 1.000000001p-1075 -> 1p-1074 Inexact Underflow
27 | pos 1.8p-1075 -> 1p-1074 Inexact Underflow
28 | pos 0.ffffffffffff8p-1074 -> 1p-1074 Inexact Underflow
29 | pos 0.ffffffffffffffffffffp-1074 -> 1p-1074 Inexact Underflow
30 |
31 | # 1p-1074 exactly representable
32 | pos 1p-1074 -> 1p-1074 Underflow
33 |
34 | # values in (1p-1074, 1.8p-1074) -> 1p-1074 Inexact Underflow
35 | pos 1.7p-1074 -> 1p-1074 Inexact Underflow
36 | pos 1.7ffffffffffffp-1074 -> 1p-1074 Inexact Underflow
37 | pos 1.7ffffffffffff8p-1074 -> 1p-1074 Inexact Underflow
38 |
39 | # values in [1.8p-1074, 2p-1074) -> 2p-1074 Inexact Underflow
40 | pos 1.8p-1074 -> 2p-1074 Inexact Underflow
41 | pos 1.80000000000008p-1074 -> 2p-1074 Inexact Underflow
42 | pos 1.8000000000001p-1074 -> 2p-1074 Inexact Underflow
43 | pos 2p-1074 -> 2p-1074 Underflow
44 |
45 | # test round-half-to-even at some mid-range subnormal values
46 | pos 123456p-1074 -> 123456p-1074 Underflow
47 | pos 123456.7p-1074 -> 123456p-1074 Inexact Underflow
48 | pos 123456.7ffffffffffffp-1074 -> 123456p-1074 Inexact Underflow
49 | pos 123456.8p-1074 -> 123456p-1074 Inexact Underflow
50 | pos 123456.8000000000001p-1074 -> 123457p-1074 Inexact Underflow
51 | pos 123456.9p-1074 -> 123457p-1074 Inexact Underflow
52 | pos 123456.ap-1074 -> 123457p-1074 Inexact Underflow
53 | pos 123456.bp-1074 -> 123457p-1074 Inexact Underflow
54 | pos 123456.cp-1074 -> 123457p-1074 Inexact Underflow
55 | pos 123456.dp-1074 -> 123457p-1074 Inexact Underflow
56 | pos 123456.ep-1074 -> 123457p-1074 Inexact Underflow
57 | pos 123456.fp-1074 -> 123457p-1074 Inexact Underflow
58 | pos 123457.0p-1074 -> 123457p-1074 Underflow
59 | pos 123457.1p-1074 -> 123457p-1074 Inexact Underflow
60 | pos 123457.2p-1074 -> 123457p-1074 Inexact Underflow
61 | pos 123457.3p-1074 -> 123457p-1074 Inexact Underflow
62 | pos 123457.4p-1074 -> 123457p-1074 Inexact Underflow
63 | pos 123457.5p-1074 -> 123457p-1074 Inexact Underflow
64 | pos 123457.6p-1074 -> 123457p-1074 Inexact Underflow
65 | pos 123457.7p-1074 -> 123457p-1074 Inexact Underflow
66 | pos 123457.7fffffffp-1074 -> 123457p-1074 Inexact Underflow
67 | pos 123457.7fffffff8p-1074 -> 123457p-1074 Inexact Underflow
68 | pos 123457.8p-1074 -> 123458p-1074 Inexact Underflow
69 | pos 123457.800000008p-1074 -> 123458p-1074 Inexact Underflow
70 | pos 123457.80000001p-1074 -> 123458p-1074 Inexact Underflow
71 | pos 123457.9p-1074 -> 123458p-1074 Inexact Underflow
72 |
73 | # values near smallest representable normal value, 1p-1022
74 | pos 0.8p-1022 -> 0.8p-1022 Underflow
75 |
76 | # write e for 2**-53, t for 1p-1022, then:
77 | #
78 | # (1-2e)t -> Underflow # exactly representable
79 | # ((1-2e)t, (1-e)t) -> (1-2e)t Inexact Underflow
80 | # [(1-e)t, (1-e/2)t) -> t Inexact Underflow
81 | # [(1-e/2)t, t) -> t Inexact # no underflow! after rounding at work
82 |
83 | pos 0.fffffffffffffp-1022 -> 0.fffffffffffffp-1022 Underflow
84 | pos 0.fffffffffffff00000000001p-1022 -> 0.fffffffffffffp-1022 Inexact Underflow
85 | pos 0.fffffffffffff4p-1022 -> 0.fffffffffffffp-1022 Inexact Underflow
86 | pos 0.fffffffffffff7ffffffffffp-1022 -> 0.fffffffffffffp-1022 Inexact Underflow
87 | pos 0.fffffffffffff8p-1022 -> 1p-1022 Inexact Underflow
88 | pos 0.fffffffffffffbffffffffffp-1022 -> 1p-1022 Inexact Underflow
89 | pos 0.fffffffffffffcp-1022 -> 1p-1022 Inexact
90 | pos 0.ffffffffffffffffffffffffp-1022 -> 1p-1022 Inexact
91 | pos 1p-1022 -> 1p-1022
92 | pos 1p+1024 -> inf Inexact Overflow
93 |
--------------------------------------------------------------------------------
/bigfloat/formatting.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 | """
18 | Helper functions for formatting.
19 |
20 | """
21 | import re
22 |
23 | from bigfloat.rounding_mode import (
24 | ROUND_TIES_TO_EVEN,
25 | ROUND_TOWARD_ZERO,
26 | ROUND_TOWARD_POSITIVE,
27 | ROUND_TOWARD_NEGATIVE,
28 | ROUND_AWAY_FROM_ZERO,
29 | )
30 |
31 | # Regular expression matching valid format specifiers.
32 | _parse_format_specifier_regex = re.compile(
33 | r"""\A
34 | (?:
35 | (?P.)?
36 | (?P[<>=^])
37 | )?
38 | (?P[-+ ])?
39 | (?P\#)?
40 | (?P0)?
41 | (?P[0-9]*)
42 | (?P\.[0-9]+)?
43 | (?P[UDYZN])?
44 | (?P[aAbeEfFgG%])?
45 | \Z""",
46 | re.VERBOSE | re.DOTALL,
47 | )
48 |
49 |
50 | rounding_mode_from_specifier = {
51 | "U": ROUND_TOWARD_POSITIVE,
52 | "D": ROUND_TOWARD_NEGATIVE,
53 | "Y": ROUND_AWAY_FROM_ZERO,
54 | "Z": ROUND_TOWARD_ZERO,
55 | "N": ROUND_TIES_TO_EVEN,
56 | }
57 |
58 |
59 | def parse_format_specifier(specification):
60 | """
61 | Parse the given format specification and return a dictionary
62 | containing relevant values.
63 |
64 | """
65 | m = _parse_format_specifier_regex.match(specification)
66 | if m is None:
67 | raise ValueError(
68 | "Invalid format specifier: {!r}".format(specification)
69 | )
70 | format_dict = m.groupdict("")
71 |
72 | # Convert zero-padding into fill and alignment.
73 | zeropad = format_dict.pop("zeropad")
74 | if zeropad:
75 | # If zero padding is requested, fill and align fields should be absent.
76 | if format_dict["align"]:
77 | raise ValueError(
78 | "Invalid format specifier: {!r}".format(specification)
79 | )
80 | # Impossible to have 'fill' without 'align'.
81 | assert not format_dict["fill"]
82 | format_dict["align"] = "="
83 | format_dict["fill"] = "0"
84 |
85 | # Default alignment is right-aligned.
86 | if not format_dict["align"]:
87 | format_dict["align"] = ">"
88 |
89 | # Default fill character is space.
90 | if not format_dict["fill"]:
91 | format_dict["fill"] = " "
92 |
93 | # Default sign is '-'.
94 | if not format_dict["sign"]:
95 | format_dict["sign"] = "-"
96 |
97 | # Convert minimum width to an int; default is zero.
98 | format_dict["minimumwidth"] = int(format_dict["minimumwidth"] or "0")
99 |
100 | # Convert precision to an int, or `None` if no precision given.
101 | if format_dict["precision"]:
102 | format_dict["precision"] = int(format_dict["precision"][1:])
103 | else:
104 | format_dict["precision"] = None
105 |
106 | # If no rounding mode is given, assume 'N'.
107 | if not format_dict["rounding"]:
108 | format_dict["rounding"] = "N"
109 |
110 | return format_dict
111 |
112 |
113 | def format_align(sign, body, spec):
114 | """Given an unpadded, non-aligned numeric string 'body' and sign
115 | string 'sign', add padding and alignment conforming to the given
116 | format specifier dictionary 'spec' (as produced by
117 | parse_format_specifier).
118 |
119 | """
120 | padding = spec["fill"] * (spec["minimumwidth"] - len(sign) - len(body))
121 | align = spec["align"]
122 | if align == "<":
123 | result = sign + body + padding
124 | elif align == ">":
125 | result = padding + sign + body
126 | elif align == "=":
127 | result = sign + padding + body
128 | elif align == "^":
129 | half = len(padding) // 2
130 | result = padding[:half] + sign + body + padding[half:]
131 | else:
132 | raise ValueError("Unrecognised alignment field: {!r}".format(align))
133 |
134 | return result
135 |
--------------------------------------------------------------------------------
/bigfloat/test/test_data/various.bft:
--------------------------------------------------------------------------------
1 | # The following tests are not supposed to be exhaustive tests of the behaviour
2 | # of the individual functions; that job is left to the MPFR test suite.
3 | # Instead, they're supposed to exercise the functions to catch simple errors
4 | # like mismatches in wrapping. So we only need to check one or two
5 | # characteristic values per function. The test values below were computed
6 | # using independent sources (mainly Pari/GP).
7 |
8 | context double_precision
9 | context RoundTiesToEven
10 |
11 | # Powers.
12 | sqr 1.8p0 -> 2.4p0
13 | rec_sqrt 2.4p0 -> 0.aaaaaaaaaaaaa8p0 Inexact
14 | cbrt 2p0 -> 1.428a2f98d728bp+0 Inexact
15 |
16 | # Log and exponential functions.
17 | log 2p0 -> 1.62e42fefa39efp-1 Inexact
18 | log2 2.8p0 -> 1.5269e12f346e3p+0 Inexact
19 | log10 1p4 -> 1.34413509f79ffp+0 Inexact
20 | log1p 0.8p0 -> 1.9f323ecbf984cp-2 Inexact
21 |
22 | exp 1p-2 -> 1.48b5e3c3e8186p+0 Inexact
23 | exp2 1p-2 -> 1.306fe0a31b715p+0 Inexact
24 | exp10 1p-2 -> 1.c73d51c54470ep+0 Inexact
25 | expm1 0.8p0 -> 1.4c2531c3c0d38p-1 Inexact
26 |
27 | # Trigonometric functions and their inverses.
28 | cos 2p0 -> -1.aa22657537205p-2 Inexact
29 | sin 2p0 -> 1.d18f6ead1b446p-1 Inexact
30 | tan 2p0 -> -1.17af62e0950f8p+1 Inexact
31 | sec 2p0 -> -1.33956fecf9e48p+1 Inexact
32 | csc 2p0 -> 1.19893a272f912p+0 Inexact
33 | cot 2p0 -> -1.d4a42e92faa4ep-2 Inexact
34 |
35 | acos 0.8p0 -> 1.0c152382d7366p+0 Inexact
36 | asin 0.8p0 -> 1.0c152382d7366p-1 Inexact
37 | atan 0.8p0 -> 1.dac670561bb4fp-2 Inexact
38 |
39 | # Hyperbolic trigonometric functions and their inverses.
40 | cosh 0.8p0 -> 1.20ac1862ae8d0p+0 Inexact
41 | sinh 0.8p0 -> 1.0acd00fe63b97p-1 Inexact
42 | tanh 0.8p0 -> 1.d9353d7568af3p-2 Inexact
43 | sech 0.8p0 -> 1.c60d1ff040dd0p-1 Inexact
44 | csch 0.8p0 -> 1.eb45dc88defedp+0 Inexact
45 | coth 0.8p0 -> 1.14fc6ceb099bfp+1 Inexact
46 |
47 | acosh 1.8p0 -> 1.ecc2caec5160ap-1 Inexact
48 | asinh 0.8p0 -> 1.ecc2caec5160ap-2 Inexact
49 | atanh 0.8p0 -> 1.193ea7aad030bp-1 Inexact
50 |
51 | # Other transcendental functions.
52 | eint 1.8p0 -> 1.a690858762f6bp+1 Inexact
53 | li2 0.cp0 -> 1.f4f9f0b58b974p-1 Inexact
54 | gamma 2.8p0 -> 1.544fa6d47b390p+0 Inexact
55 | gamma_inc 0.5p0 1.7p0 -> 0x1.1b29c8af307e2p-3 Inexact
56 | lngamma 2.8p0 -> 1.2383e809a67e8p-2 Inexact
57 | digamma 2.8p0 -> 1.680425af12b5ep-1 Inexact
58 | beta 0.5p0 1.7p0 -> 0x1.619aaeeb6cb2bp+1 Inexact
59 | zeta 4.0p0 -> 1.151322ac7d848p+0 Inexact
60 | erf 3.8p0 -> 1.ffffe710d565ep-1 Inexact
61 | erfc 3.8p0 -> 1.8ef2a9a18d857p-21 Inexact
62 | agm 1p0 1.6a09e667f3bcdp+0 -> 1.32b95184360ccp+0 Inexact
63 | ai 0.ap0 -> 1.a2db43a6d812dp-3 Inexact
64 |
65 | # Arithmetic functions not tested elsewhere.
66 | dim 2.8p0 1p0 -> 1.8p0
67 | dim 1p0 2.8p0 -> 0p0
68 | fma 3p0 5p0 8p0 -> 17p0
69 | fms 3p0 5p0 8p0 -> 7p0
70 | fmma 3 5 8 9 -> 0x57
71 | fmms 3 5 8 9 -> -0x39
72 |
73 | hypot 5p0 cp0 -> dp0
74 |
75 | floor -1p0 -> -1p0
76 | floor -0.dp0 -> -1p0
77 | floor -0.1p0 -> -1p0
78 | floor -0p0 -> -0p0
79 | floor 0p0 -> 0p0
80 | floor 0.1p0 -> 0p0
81 | floor 0.dp0 -> 0p0
82 | floor 1p0 -> 1p0
83 |
84 | ceil -1p0 -> -1p0
85 | ceil -0.dp0 -> -0p0
86 | ceil -0.1p0 -> -0p0
87 | ceil -0p0 -> -0p0
88 | ceil 0p0 -> 0p0
89 | ceil 0.1p0 -> 1p0
90 | ceil 0.dp0 -> 1p0
91 | ceil 1p0 -> 1p0
92 |
93 | round -1.8p0 -> -2p0
94 | round -1p0 -> -1p0
95 | round -0.8p0 -> -1p0
96 | round -0.dp0 -> -1p0
97 | round -0.1p0 -> -0p0
98 | round -0p0 -> -0p0
99 | round 0p0 -> 0p0
100 | round 0.1p0 -> 0p0
101 | round 0.8p0 -> 1p0
102 | round 0.dp0 -> 1p0
103 | round 1p0 -> 1p0
104 | round 1.8p0 -> 2p0
105 |
106 | roundeven -1.8p0 -> -2p0
107 | roundeven -1p0 -> -1p0
108 | roundeven -0.8p0 -> -0p0
109 | roundeven -0.dp0 -> -1p0
110 | roundeven -0.1p0 -> -0p0
111 | roundeven -0p0 -> -0p0
112 | roundeven 0p0 -> 0p0
113 | roundeven 0.1p0 -> 0p0
114 | roundeven 0.8p0 -> 0p0
115 | roundeven 0.dp0 -> 1p0
116 | roundeven 1p0 -> 1p0
117 | roundeven 1.8p0 -> 2p0
118 |
119 | trunc -1p0 -> -1p0
120 | trunc -0.dp0 -> -0p0
121 | trunc -0.1p0 -> -0p0
122 | trunc -0p0 -> -0p0
123 | trunc 0p0 -> 0p0
124 | trunc 0.1p0 -> 0p0
125 | trunc 0.dp0 -> 0p0
126 | trunc 1p0 -> 1p0
127 |
128 | frac -1p0 -> -0p0
129 | frac -0.dp0 -> -0.dp0
130 | frac -0.1p0 -> -0.1p0
131 | frac -0p0 -> -0p0
132 | frac 0p0 -> 0p0
133 | frac 0.1p0 -> 0.1p0
134 | frac 0.dp0 -> 0.dp0
135 | frac 1p0 -> 0p0
136 |
137 | remainder -5p0 3p0 -> 1p0
138 | remainder -4p0 3p0 -> -1p0
139 | remainder -3p0 3p0 -> -0p0
140 | remainder -2p0 3p0 -> 1p0
141 | remainder -1p0 3p0 -> -1p0
142 | remainder -0p0 3p0 -> -0p0
143 | remainder 0p0 3p0 -> 0p0
144 | remainder 1p0 3p0 -> 1p0
145 | remainder 2p0 3p0 -> -1p0
146 | remainder 3p0 3p0 -> 0p0
147 | remainder 4p0 3p0 -> 1p0
148 | remainder 5p0 3p0 -> -1p0
149 |
--------------------------------------------------------------------------------
/examples/lanczos_coeffs.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | # Computing the gamma function via Lanczos' formula
19 | #
20 | # See document at:
21 | #
22 | # http://www.boost.org/doc/libs/1_40_0/libs/math/doc/sf_and_dist/html/math_toolkit/backgrounders/lanczos.html
23 | #
24 | # for more. Note that the formula for a_0 on that page is invalid, involving
25 | # a (-1)!. But in general, the j=0 term of the sum for a_k is
26 | # (k-1)!/(k)! = 1/k, and multiplying by k gives 0.
27 |
28 | # The reference
29 | #
30 | # http://my.fit.edu/~gabdo/gamma.txt (Paul Godfrey) gives instead
31 | # the formulas:
32 | #
33 | # z! = sqrt(2*pi)*(z+g+1/2)^(z+1/2)*exp(-(z+g+1/2))*Ag(z)
34 |
35 | # Ag(z) = 1/2*p(0) + z/(z+1)*p(1) + z*(z-1)/(z+1)/(z+2)*p(2) + ...
36 |
37 | # p(k) = sum_{j=0}^k C(2k, 2j)*F(g, j)
38 |
39 | # C(2k, 2j) : coefficients of the Chebyshev polynomials of the
40 | # first kind. (1, x, 2x^2-1, 4x^3-3x, ...). Thus:
41 | #
42 | # C(0, 0) = 1
43 | # C(2, 0) = -1, C(2, 2) = 2
44 | # C(4, 0) = 1, C(4, 2) = -8, C(4, 4) = 8
45 |
46 | # sequence A053120.
47 | #
48 | # if C(n, m) = coefficient of x**m in nth poly, then
49 | # C(n, 0) = (-1)**(n/2) (n even)
50 | # C(n, m) = (-1)**((n+m)/2 + m) * (2**(m-1))*n*binomial((n+m)/2-1, m-1)/m
51 |
52 | # Hence:
53 | #
54 | # C(2k, 2j) = (-1)**(j+k) 2**(2j-1) 2k binomial(k+j-1, 2j-1) / (2j)
55 | # = (-1)**(j+k) 2**2j (k+j-1)! / (2j)! / (k-j)! * k
56 | # absorbing the (2j)!/j!/2**(2j) from F(g, j) gives:
57 | # = (-1)**(j+k) (k+j-1)! * k / (k-j)! / j!
58 |
59 | # Okay, so that works in
60 |
61 |
62 | # F(g, j) = sqrt(2)/pi * (j-1/2)!*(j+g+1/2)^-(j+1/2)*exp(j+g+1/2)
63 |
64 | # note that (j-1/2)! = (j-1/2)*(j-3/2)*...*(1/2) * sqrt(pi)
65 | # = (2*j-1)*(2*j-3)*...*2 * sqrt(pi) / 2**j
66 | # = (2*j)!/j!/2**(2j) * sqrt(pi)
67 |
68 |
69 | from __future__ import division
70 | from math import factorial
71 | import bigfloat
72 | from bigfloat import exp
73 |
74 |
75 | def M(k, j):
76 | # returns an integer, the combinatorial coefficient in the
77 | # Lanczos formula.
78 | assert 0 <= j and 0 <= k
79 | if j == k == 0:
80 | return 1
81 | if j > k:
82 | return 0
83 | top = (-1) ** (k + j) * factorial(j + k - 1) * k
84 | bottom = factorial(k - j) * factorial(j)
85 | assert top % bottom == 0
86 | return top // bottom
87 |
88 |
89 | def H(g, j):
90 | return exp(j + g + 0.5) / (j + g + 0.5) ** (j + 0.5)
91 |
92 |
93 | def b(j, N):
94 | assert 0 <= j <= N - 1
95 | coeffs = [1]
96 | facs = list(range(j, N - 1)) + list(range(-1, -j - 1, -1))
97 | for i in facs:
98 | # multiply by (z+i)
99 | times_z = [0] + coeffs
100 | times_i = [i * c for c in coeffs] + [0]
101 | coeffs = [a + b for a, b in zip(times_z, times_i)]
102 | assert len(coeffs) == N
103 | return coeffs
104 |
105 |
106 | def Lg_num_coeffs(g, N):
107 | B = [b(j, N) for j in range(N)]
108 | MM = [
109 | [(M(k, j) if k == 0 else 2 * M(k, j)) for j in range(N)]
110 | for k in range(N)
111 | ]
112 | # BTM has only integer entries
113 | BTM = [
114 | [sum(B[k][l] * MM[k][j] for k in range(N)) for j in range(N)]
115 | for l in range(N)
116 | ]
117 |
118 | HH = [H(g, j) for j in range(N)]
119 | coeffs = [sum(BTM[i][j] * HH[j] for j in range(N)) for i in range(N)]
120 | return coeffs
121 |
122 |
123 | def Lg_den_coeffs(g, N):
124 | return b(0, N)
125 |
126 |
127 | def L(g, z, N):
128 | num_coeffs = Lg_num_coeffs(g, N)
129 | den_coeffs = Lg_den_coeffs(g, N)
130 |
131 | num = 0.0
132 | for c in reversed(num_coeffs):
133 | num = num * z + c
134 | den = 0.0
135 | for c in reversed(den_coeffs):
136 | den = den * z + c
137 | return num / den
138 |
139 |
140 | def gamma(z, g, N):
141 | return (z + g - 0.5) ** (z - 0.5) / exp(z + g - 0.5) * L(g, z, N)
142 |
143 |
144 | # Now express everything as a rational function; we want to be
145 | # able to figure out the coefficient of p_j z^k in the numerator.
146 | # Let's call this coefficient b(j, k). It depends on N.
147 | # b(j, N)[k] is the coefficient of p_j z^k in the numerator.
148 | # except: b(0, N)[k] is the coefficient of p_0/2 z^k in the numerator.
149 |
150 | p = 300 # bits of precision to use for computation
151 | g = bigfloat.BigFloat(6.024680040776729583740234375)
152 | N = 13
153 |
154 | with bigfloat.precision(p):
155 | print("Numerator coefficients:")
156 | for c in Lg_num_coeffs(g, N):
157 | print(c)
158 |
159 | print("Denominator coefficients:")
160 | for c in Lg_den_coeffs(g, N):
161 | print(c)
162 |
--------------------------------------------------------------------------------
/examples/contfrac.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | """
19 | The documentation for mpfr_get_str, for converting a precision n
20 | number into a base b string, says:
21 |
22 | "the chosen precision of str is the minimal precision depending on
23 | n and b only that satisfies the above property, i.e., m = 1 +
24 | ceil(n*log(2)/log(b)), but in some very rare cases, it might be
25 | m+1."
26 |
27 | In this script, we compute the smallest precisions for which this
28 | 'very rare' case occurs, for each base b in the range 2 <= b <= 62.
29 | We compare our results with those computed by Paul Zimmerman.
30 |
31 | """
32 |
33 | from fractions import Fraction
34 | from bigfloat import log2, div, precision, next_up
35 | from bigfloat import RoundTowardPositive, RoundTowardNegative
36 |
37 |
38 | def semiconvergents(x):
39 | """Semiconvergents of continued fraction expansion of a Fraction x."""
40 |
41 | (q, n), d = divmod(x.numerator, x.denominator), x.denominator
42 | yield Fraction(q)
43 | p0, q0, p1, q1 = 1, 0, q, 1
44 | while n:
45 | (q, n), d = divmod(d, n), n
46 | for _ in range(q):
47 | p0, q0 = p0 + p1, q0 + q1
48 | yield Fraction(p0, q0)
49 | p0, q0, p1, q1 = p1, q1, p0, q0
50 |
51 |
52 | def logn2(n, p):
53 | """Best p-bit lower and upper bounds for log(2)/log(n), as Fractions."""
54 | with precision(p):
55 | extra = 10
56 | while True:
57 | with precision(p + extra):
58 | # use extra precision for intermediate step
59 | log2upper = log2(n, RoundTowardPositive)
60 | log2lower = log2(n, RoundTowardNegative)
61 |
62 | lower = div(1, log2upper, RoundTowardNegative)
63 | upper = div(1, log2lower, RoundTowardPositive)
64 |
65 | # if lower and upper are adjacent (or equal) we're done
66 | if next_up(lower) == upper:
67 | return (
68 | Fraction(*lower.as_integer_ratio()),
69 | Fraction(*upper.as_integer_ratio()),
70 | )
71 |
72 | # otherwise, increase the precision and try again
73 | extra += 10
74 |
75 |
76 | marks_results = {}
77 | all_n = [n for n in range(3, 63) if n & (n - 1)]
78 | for n in all_n:
79 | # 76-bit upper approximation used for the computation of m
80 | approx = logn2(n, 76)[1]
81 | # Find first semiconvergent s s.t. log(2)/log(n) < s < approx. To
82 | # get semiconvergents of log(2)/log(n), get lower and upper bounds,
83 | # find semiconvergents of those, then use the matching initial portions
84 | # of the two lists.
85 | l, u = logn2(n, 100) # 100 seems to be big enough
86 | for lc, uc in zip(semiconvergents(l), semiconvergents(u)):
87 | if lc != uc:
88 | raise RuntimeError("not enough semiconvergents")
89 | if u <= lc < approx:
90 | marks_results[n] = lc.denominator
91 | break
92 |
93 | # from http://websympa.loria.fr/wwsympa/arc/mpfr/2009-06/msg00034.html:
94 | check_values = r"""
95 | 3, 975675645481 & 21, 500866275153 & 37, 1412595553751 & 52, 4234025992181\\
96 | 5, 751072483167 & 22, 1148143737877 & 38, 2296403499681 & 53, 1114714558973\\
97 | 6, 880248760192 & 23, 2963487537029 & 39, 227010038198 & 54, 653230957562 \\
98 | 7, 186564318007 & 24, 930741237529 & 40, 3574908346547 & 55, 1113846215983\\
99 | 9, 1951351290962 & 25, 751072483167 & 41, 458909109357 & 56, 385930970803 \\
100 | 10, 1074541795081 & 26, 1973399062219 & 42, 1385773590791 & 57, 676124411642 \\
101 | 11, 890679595344 & 27, 1193652440098 & 43, 945885487008 & 58, 330079387370 \\
102 | 12, 727742578896 & 28, 319475419871 & 44, 1405607880410 & 59, 276902299279 \\
103 | 13, 1553566199646 & 29, 1645653531910 & 45, 421759749499 & 60, 2304608467893\\
104 | 14, 253019868939 & 30, 1190119072066 & 46, 376795094250 & 61, 1364503143363\\
105 | 15, 947578699731 & 31, 2605117443408 & 47, 1352868311988 & 62, 414481628603 \\
106 | 17, 628204683310 & 33, 1138749817330 & 48, 1133739896162 \\
107 | 18, 2280193268258 & 34, 1611724268329 & 49, 186564318007 \\
108 | 19, 2290706306707 & 35, 820222240621 & 50, 842842574535 \\
109 | 20, 645428387961 & 36, 1760497520384 & 51, 1435927298893 \\
110 | """
111 |
112 | pauls_results = dict(
113 | map(int, piece.split(","))
114 | for line in check_values.rstrip("\\\n").split(r"\\")
115 | for piece in line.split("&")
116 | )
117 |
118 | print("{0:4s} {1:15s}".format("base", "precision"))
119 | print("{0:4s} {1:15s}".format("====", "==============="))
120 | for b, n in sorted(marks_results.items()):
121 | print("{0:4d} {1:15d}".format(b, n))
122 | results_match = marks_results == pauls_results
123 | print("Results match Paul Zimmerman's: {}".format(results_match))
124 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = build
9 |
10 | # User-friendly check for sphinx-build
11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13 | endif
14 |
15 | # Internal variables.
16 | PAPEROPT_a4 = -D latex_paper_size=a4
17 | PAPEROPT_letter = -D latex_paper_size=letter
18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
19 | # the i18n builder cannot share the environment and doctrees with the others
20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
21 |
22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
23 |
24 | help:
25 | @echo "Please use \`make ' where is one of"
26 | @echo " html to make standalone HTML files"
27 | @echo " dirhtml to make HTML files named index.html in directories"
28 | @echo " singlehtml to make a single large HTML file"
29 | @echo " pickle to make pickle files"
30 | @echo " json to make JSON files"
31 | @echo " htmlhelp to make HTML files and a HTML help project"
32 | @echo " qthelp to make HTML files and a qthelp project"
33 | @echo " devhelp to make HTML files and a Devhelp project"
34 | @echo " epub to make an epub"
35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38 | @echo " text to make text files"
39 | @echo " man to make manual pages"
40 | @echo " texinfo to make Texinfo files"
41 | @echo " info to make Texinfo files and run them through makeinfo"
42 | @echo " gettext to make PO message catalogs"
43 | @echo " changes to make an overview of all changed/added/deprecated items"
44 | @echo " xml to make Docutils-native XML files"
45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46 | @echo " linkcheck to check all external links for integrity"
47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48 |
49 | clean:
50 | rm -rf $(BUILDDIR)/*
51 |
52 | html:
53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54 | @echo
55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56 |
57 | dirhtml:
58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
59 | @echo
60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
61 |
62 | singlehtml:
63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
64 | @echo
65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
66 |
67 | pickle:
68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
69 | @echo
70 | @echo "Build finished; now you can process the pickle files."
71 |
72 | json:
73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
74 | @echo
75 | @echo "Build finished; now you can process the JSON files."
76 |
77 | htmlhelp:
78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
79 | @echo
80 | @echo "Build finished; now you can run HTML Help Workshop with the" \
81 | ".hhp project file in $(BUILDDIR)/htmlhelp."
82 |
83 | qthelp:
84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
85 | @echo
86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/bigfloat.qhcp"
89 | @echo "To view the help file:"
90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/bigfloat.qhc"
91 |
92 | devhelp:
93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
94 | @echo
95 | @echo "Build finished."
96 | @echo "To view the help file:"
97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/bigfloat"
98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/bigfloat"
99 | @echo "# devhelp"
100 |
101 | epub:
102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
103 | @echo
104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
105 |
106 | latex:
107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
108 | @echo
109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
111 | "(use \`make latexpdf' here to do that automatically)."
112 |
113 | latexpdf:
114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
115 | @echo "Running LaTeX files through pdflatex..."
116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
118 |
119 | latexpdfja:
120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121 | @echo "Running LaTeX files through platex and dvipdfmx..."
122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
124 |
125 | text:
126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
127 | @echo
128 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
129 |
130 | man:
131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
132 | @echo
133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
134 |
135 | texinfo:
136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
137 | @echo
138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
139 | @echo "Run \`make' in that directory to run these through makeinfo" \
140 | "(use \`make info' here to do that automatically)."
141 |
142 | info:
143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
144 | @echo "Running Texinfo files through makeinfo..."
145 | make -C $(BUILDDIR)/texinfo info
146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
147 |
148 | gettext:
149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
150 | @echo
151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
152 |
153 | changes:
154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
155 | @echo
156 | @echo "The overview file is in $(BUILDDIR)/changes."
157 |
158 | linkcheck:
159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
160 | @echo
161 | @echo "Link check complete; look for any errors in the above output " \
162 | "or in $(BUILDDIR)/linkcheck/output.txt."
163 |
164 | doctest:
165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
166 | @echo "Testing of doctests in the sources finished, look at the " \
167 | "results in $(BUILDDIR)/doctest/output.txt."
168 |
169 | xml:
170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
171 | @echo
172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
173 |
174 | pseudoxml:
175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
176 | @echo
177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
178 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | .. image:: https://travis-ci.org/mdickinson/bigfloat.svg?branch=master
2 | :alt: Status of most recent Travis CI run
3 | :target: https://travis-ci.org/mdickinson/bigfloat
4 |
5 |
6 | The bigfloat package
7 | ====================
8 |
9 | The ``bigfloat`` package is a Python package providing arbitrary-precision
10 | correctly-rounded binary floating-point arithmetic. It is implemented as a
11 | `Cython `_ wrapper around the `GNU MPFR library
12 | `_. A couple of lines of Python code should give the
13 | idea::
14 |
15 | >>> from bigfloat import *
16 | >>> with precision(200) + RoundTowardZero:
17 | ... print(sqrt(2))
18 | ...
19 | 1.4142135623730950488016887242096980785696718753769480731766796
20 | >>> with quadruple_precision:
21 | ... const_pi()
22 | ...
23 | BigFloat.exact('3.14159265358979323846264338327950280', precision=113)
24 |
25 | Features
26 | --------
27 |
28 | - Supports Python 2 (version 2.7) and Python 3 (version 3.5 or later).
29 |
30 | - Exactly reproducible correctly-rounded results across platforms;
31 | precisely-defined semantics compatible with the IEEE 754-2008 standard.
32 |
33 | - Support for mixed-type operations with Python integers and floats.
34 |
35 | - Support for emulating IEEE 754 arithmetic in any of the IEEE binary
36 | interchange formats described in IEEE 754-2008. Infinities, NaNs,
37 | signed zeros, and subnormals are all supported.
38 |
39 | - Easy control of rounding modes and precisions via ``Context`` objects
40 | and Python's ``with`` statement.
41 |
42 | Documentation
43 | -------------
44 |
45 | Full `package documentation `_ is hosted at
46 | Read the Docs. Read on for a quick tour.
47 |
48 | A quick tour
49 | ------------
50 |
51 | The ``bigfloat`` package is small and simple to use. Here's a quick
52 | tour of some of its features.
53 |
54 | For demonstration purposes, start with::
55 |
56 | >>> from bigfloat import *
57 |
58 | Note that this import shadows some builtin Python functions, namely ``abs``,
59 | ``max``, ``min``, ``pow``, ``round``, ``sum`` and (on Python 2 only) ``cmp``.
60 | In normal usage you'll probably only want to import the classes and functions
61 | that you actually need.
62 |
63 | The main class is the ``BigFloat`` class::
64 |
65 | >>> BigFloat(1) # can be constructed from an integer, float or string
66 | BigFloat.exact('1.00000000000000000000000000000000000', precision=113)
67 | >>> BigFloat('3.14159') ** 2 / 6.0 # can combine with ints and floats
68 | BigFloat.exact('1.64493128801666666666666666666666670', precision=113)
69 | >>> BigFloat('0.1', precision(200)) # high-precision value from string
70 | BigFloat.exact('0.1000000000000000000000000000000000000000000000000000
71 | 0000000002', precision=200)
72 |
73 | Newly-created ``BigFloat`` instances refer to the current *context* to
74 | determine what precision and rounding modes to use. This current
75 | context is represented by a ``Context`` instance, and can be retrieved
76 | by calling ``getcontext``::
77 |
78 | >>> getcontext()
79 | Context(precision=113, emax=16384, emin=-16493,
80 | subnormalize=True, rounding=ROUND_TIES_TO_EVEN)
81 |
82 | The ``precision(200)`` argument passed to the ``BigFloat`` constructor
83 | above is also an example of a ``Context``::
84 |
85 | >>> precision(200)
86 | Context(precision=200)
87 |
88 | The context used for a calculation can be set using the ``setcontext``
89 | function, but a better way to make a temporary change to the context
90 | is to use Python's ``with`` statement::
91 |
92 | >>> with precision(1000):
93 | ... print sqrt(2)
94 | ...
95 | 1.41421356237309504880168872420969807856967187537694807317667973
96 | 7990732478462107038850387534327641572735013846230912297024924836
97 | 0558507372126441214970999358314132226659275055927557999505011527
98 | 8206057147010955997160597027453459686201472851741864088919860955
99 | 232923048430871432145083976260362799525140798964
100 |
101 | Here, ``sqrt`` is one of a number of mathematical functions that the
102 | ``bigfloat`` package exports. As you can see, these functions operate on
103 | integers and floats as well as ``BigFloat`` instances, but always
104 | return a ``BigFloat`` instance.
105 |
106 | Rounding modes can be controlled similarly. Here are upper and lower
107 | bounds for π, accurate to 53 significant bits::
108 |
109 | >>> with RoundTowardPositive:
110 | ... const_pi()
111 | ...
112 | BigFloat.exact('3.14159265358979323846264338327950318', precision=113)
113 | >>> with RoundTowardNegative:
114 | ... const_pi()
115 | ...
116 | BigFloat.exact('3.14159265358979323846264338327950280', precision=113)
117 |
118 | And as you'd expect, ``with`` statements like those above can be
119 | nested. ``Context`` objects can also be combined using addition::
120 |
121 | >>> with RoundTowardPositive + precision(24):
122 | ... BigFloat(1) / 3
123 | ...
124 | BigFloat.exact('0.333333343', precision=24)
125 |
126 | Various ``Context`` objects corresponding to IEEE 754 interchange
127 | formats are predefined::
128 |
129 | >>> quadruple_precision
130 | Context(precision=113, emax=16384, emin=-16493, subnormalize=True)
131 | >>> half_precision
132 | Context(precision=11, emax=16, emin=-23, subnormalize=True)
133 | >>> with half_precision:
134 | log(2)
135 | ...
136 | BigFloat.exact('0.69336', precision=11)
137 |
138 | Installation
139 | ------------
140 |
141 | The ``bigfloat`` package is `available on the Python package index
142 | `_, and can be installed in the usual
143 | way using ``easy_install`` or ``pip``. Alternatively, the development sources
144 | may be downloaded from the project's `homepage
145 | `_ on GitHub.
146 |
147 | For more comprehensive installation instructions, please see the `full
148 | documentation `_.
149 |
150 | Feedback
151 | --------
152 |
153 | Feedback is welcome! Please use the `GitHub issue tracker
154 | `_ to report issues.
155 | Alternatively, you can contact Mark Dickinson directly at dickinsm@gmail.com
156 | with suggestions, complaints, bug reports, etc.
157 |
158 | License
159 | -------
160 |
161 | The bigfloat package is copyright (C) 2009--2019 Mark Dickinson
162 |
163 | The bigfloat package is free software: you can redistribute it and/or modify
164 | it under the terms of the GNU Lesser General Public License as published by
165 | the Free Software Foundation, either version 3 of the License, or (at your
166 | option) any later version.
167 |
168 | The bigfloat package is distributed in the hope that it will be useful, but
169 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
170 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
171 | for more details.
172 |
173 | You should have received a copy of the GNU Lesser General Public License
174 | along with the bigfloat package. If not, see .
175 |
176 | Links
177 | -----
178 | - `Documentation at Read the Docs `_
179 | - `Python package index `_
180 | - `Project homepage at GitHub `_
181 | - `Issue tracker `_
182 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | The bigfloat package --- high precision floating-point arithmetic
2 | =================================================================
3 |
4 | Release v\ |release|.
5 |
6 | .. module:: bigfloat
7 | :synopsis: Python wrapper for MPFR floating-point library.
8 |
9 | .. moduleauthor:: Mark Dickinson
10 |
11 | The :mod:`bigfloat` package is a Python wrapper for the `GNU MPFR library
12 | `_ for arbitrary-precision floating-point reliable
13 | arithmetic. The MPFR library is a well-known portable C library for
14 | arbitrary-precision arithmetic on floating-point numbers. It provides precise
15 | control over precisions and rounding modes and gives correctly-rounded
16 | reproducible platform-independent results.
17 |
18 | The :mod:`bigfloat` package aims to provide a convenient and friendly
19 | Python interface to the operations and functions provided by the MPFR
20 | library. The main class, :class:`BigFloat`, gives an immutable
21 | multiple-precision floating-point type that can be freely mixed with
22 | Python integers and floats. The :class:`Context` class, when used in
23 | conjunction with Python's ``with`` statement, gives a simple way of
24 | controlling precisions and rounding modes. Additional module-level
25 | functions provide various standard mathematical operations. There is
26 | full support for IEEE 754 signed zeros, nans, infinities and
27 | subnormals.
28 |
29 |
30 | Features
31 | --------
32 |
33 | - Supports Python 2 (version 2.7) and Python 3 (version 3.5 or later).
34 |
35 | - Exactly reproducible correctly-rounded results across platforms;
36 | precisely-defined semantics compatible with the IEEE 754-2008 standard.
37 |
38 | - Support for mixed-type operations with Python integers and floats.
39 |
40 | - Support for emulating IEEE 754 arithmetic in any of the IEEE binary
41 | interchange formats described in IEEE 754-2008. Infinities, NaNs,
42 | signed zeros, and subnormals are all supported.
43 |
44 | - Easy control of rounding modes and precisions via ``Context`` objects
45 | and Python's ``with`` statement.
46 |
47 |
48 | Introduction
49 | ------------
50 |
51 | Here's a quick tour::
52 |
53 | >>> from bigfloat import *
54 | >>> sqrt(2, precision(100)) # compute sqrt(2) with 100 bits of precision
55 | BigFloat.exact('1.4142135623730950488016887242092', precision=100)
56 | >>> with precision(100): # another way to get the same result
57 | ... sqrt(2)
58 | ...
59 | BigFloat.exact('1.4142135623730950488016887242092', precision=100)
60 | >>> my_context = precision(100) + RoundTowardPositive
61 | >>> my_context
62 | Context(precision=100, rounding='RoundTowardPositive')
63 | >>> sqrt(2, my_context) # and another, this time rounding up
64 | BigFloat.exact('1.4142135623730950488016887242108', precision=100)
65 | >>> with RoundTowardNegative: # a lower bound for zeta(2)
66 | ... sum(1/sqr(n) for n in range(1, 10000))
67 | ...
68 | BigFloat.exact('1.6448340618469506', precision=53)
69 | >>> zeta(2) # actual value, for comparison
70 | BigFloat.exact('1.6449340668482264', precision=53)
71 | >>> const_pi()**2/6.0 # double check value
72 | BigFloat.exact('1.6449340668482264', precision=53)
73 | >>> quadruple_precision # context implementing IEEE 754 binary128 format
74 | Context(precision=113, emax=16384, emin=-16493, subnormalize=True)
75 | >>> next_up(0, quadruple_precision) # smallest subnormal for binary128
76 | BigFloat.exact('6.47517511943802511092443895822764655e-4966', precision=113)
77 | >>> log2(_)
78 | BigFloat.exact('-16494.000000000000', precision=53)
79 |
80 |
81 | Installation
82 | ------------
83 |
84 | Where to get it
85 | ^^^^^^^^^^^^^^^
86 |
87 | The latest released version of the :mod:`bigfloat` package can be obtained from
88 | the `Python Package Index `_.
89 | Development sources can be checked out from the project's `GitHub page
90 | `_.
91 |
92 |
93 | Prerequisites
94 | ^^^^^^^^^^^^^
95 |
96 | The :mod:`bigfloat` package works with Python 2 (version 2.7) or
97 | Python 3 (version 3.5 or later). It uses a single codebase for both Python
98 | dialects, so the same source works on both dialects of Python.
99 |
100 | Whether installing ``bigfloat`` from source or from the Python Package Index,
101 | you will need to have both the GMP and MPFR libraries already installed on your
102 | system, along with the include files for those libraries. See the `MPFR
103 | homepage `_ and the `GMP homepage `_
104 | for more information about these libraries. Currently, MPFR version 3.0.0 or
105 | later is required.
106 |
107 | On Ubuntu, prerequisites can be installed with::
108 |
109 | sudo apt-get install libmpfr-dev
110 |
111 | On Fedora Linux, use (for example)::
112 |
113 | su -c "yum install mpfr-devel"
114 |
115 | On other flavours of Linux, some variant of one of the above should work.
116 |
117 |
118 | Installation from the Python Package Index
119 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
120 |
121 | Once you have the prerequisites described above installed, the recommended
122 | method for installation is to use `pip`_::
123 |
124 | pip install bigfloat
125 |
126 | If you prefer, you can use the ``easy_install`` command from `setuptools`_::
127 |
128 | easy-install bigfloat
129 |
130 | Depending on your system, you may need superuser privileges for the install.
131 | For example::
132 |
133 | sudo pip install bigfloat
134 |
135 | If the MPFR and GMP libraries are installed in an unusual location, you may
136 | need to set appropriate environment variables when installing. For example, on
137 | an OS X 10.9 system with MPFR and GMP installed in /opt/local, I need to do::
138 |
139 | sudo LIBRARY_PATH=/opt/local/lib CPATH=/opt/local/include pip install bigfloat
140 |
141 | Platform-specific installation instructions
142 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
143 |
144 | On a newly-installed version of Ubuntu 14.04LTS (trusty), the commands below
145 | are enough to install bigfloat for Python 3, from scratch. You may not need
146 | the first line if you already have ``pip`` and the Python development headers
147 | installed.
148 |
149 | ::
150 |
151 | sudo apt-get install python3-dev python3-pip
152 | sudo apt-get install libmpfr-dev
153 | sudo pip3 install bigfloat
154 |
155 | For Python 2, the procedure is similar::
156 |
157 | sudo apt-get install python-dev python-pip
158 | sudo apt-get install libmpfr-dev
159 | sudo pip install bigfloat
160 |
161 | On Fedora 20, the following sequence of commands worked for me (for Python 3;
162 | again, remove all occurrences of ``3`` to get the commands for Python 2)::
163 |
164 | su -c "yum install gcc python3-devel python3-pip"
165 | su -c "yum install mpfr-devel"
166 | su -c "pip-python3 install bigfloat"
167 |
168 |
169 | Installation from source
170 | ^^^^^^^^^^^^^^^^^^^^^^^^
171 |
172 | Installation from source (for example, from a GitHub checkout, or from an
173 | unpacked source distribution), is similar to installation from the Python
174 | Package Index: the only difference is that you should use the ``setup.py ``
175 | script instead of using ``pip`` or ``easy_install``. On many systems,
176 | installation should be as simple as typing::
177 |
178 | python setup.py install
179 |
180 | in the top-level directory of the unpacked distribution. As above, you may
181 | need superuser privileges to install the library, for example with::
182 |
183 | sudo python setup.py install
184 |
185 | Again as above, if the libraries and include files are installed in an
186 | unusual place, it may be necessary to specify their location using environment
187 | variables on the command line. For example::
188 |
189 | LIBRARY_PATH=/opt/local/lib CPATH=/opt/local/include python setup.py install
190 |
191 |
192 | Detailed Documentation
193 | ======================
194 |
195 | .. toctree::
196 | :maxdepth: 2
197 |
198 | tutorial/index
199 | reference/index
200 |
201 |
202 | Indices and tables
203 | ==================
204 |
205 | * :ref:`genindex`
206 |
207 | .. _pip: https://pypi.python.org/pypi/pip
208 | .. _setuptools: https://pypi.python.org/pypi/setuptools
209 |
--------------------------------------------------------------------------------
/bigfloat/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | __all__ = [
19 | # version string for bigfloat
20 | "__version__",
21 | # main class
22 | "BigFloat",
23 | # contexts
24 | "Context",
25 | # limits on emin, emax and precision
26 | "EMIN_MIN",
27 | "EMIN_MAX",
28 | "EMAX_MIN",
29 | "EMAX_MAX",
30 | "PRECISION_MIN",
31 | "PRECISION_MAX",
32 | # rounding mode constants
33 | "ROUND_TIES_TO_EVEN",
34 | "ROUND_TOWARD_ZERO",
35 | "ROUND_TOWARD_POSITIVE",
36 | "ROUND_TOWARD_NEGATIVE",
37 | "ROUND_AWAY_FROM_ZERO",
38 | # context constants...
39 | "DefaultContext",
40 | "EmptyContext",
41 | "half_precision",
42 | "single_precision",
43 | "double_precision",
44 | "quadruple_precision",
45 | "RoundTiesToEven",
46 | "RoundTowardZero",
47 | "RoundTowardPositive",
48 | "RoundTowardNegative",
49 | "RoundAwayFromZero",
50 | # ... and functions
51 | "IEEEContext",
52 | "precision",
53 | "extra_precision",
54 | "rounding",
55 | # get and set current context
56 | "getcontext",
57 | "setcontext",
58 | # flags
59 | "Inexact",
60 | "Overflow",
61 | "Underflow",
62 | "NanFlag",
63 | "ZeroDivision",
64 | # functions to test, set and clear individual flags
65 | "test_flag",
66 | "set_flag",
67 | "clear_flag",
68 | # and to get and set the entire flag state
69 | "set_flagstate",
70 | "get_flagstate",
71 | # numeric functions
72 | "next_up",
73 | "next_down",
74 | # 5.2 Assignment Functions
75 | "pos",
76 | # 5.4 Conversion functions
77 | "frexp",
78 | # 5.5 Basic arithmetic functions
79 | "add",
80 | "sub",
81 | "mul",
82 | "sqr",
83 | "div",
84 | "sqrt",
85 | "rec_sqrt",
86 | "cbrt",
87 | "root",
88 | "rootn",
89 | "pow",
90 | "neg",
91 | "abs",
92 | "dim",
93 | "floordiv",
94 | "mod",
95 | # 5.6 Comparison functions
96 | "cmp",
97 | "cmpabs",
98 | "is_nan",
99 | "is_inf",
100 | "is_finite",
101 | "is_zero",
102 | "is_regular",
103 | "sgn",
104 | "greater",
105 | "greaterequal",
106 | "less",
107 | "lessequal",
108 | "equal",
109 | "notequal",
110 | "lessgreater",
111 | "unordered",
112 | # 5.7 Special Functions
113 | "log",
114 | "log2",
115 | "log10",
116 | "log1p",
117 | "exp",
118 | "exp2",
119 | "exp10",
120 | "expm1",
121 | "cos",
122 | "sin",
123 | "tan",
124 | "sec",
125 | "csc",
126 | "cot",
127 | "acos",
128 | "asin",
129 | "atan",
130 | "atan2",
131 | "cosh",
132 | "sinh",
133 | "tanh",
134 | "sech",
135 | "csch",
136 | "coth",
137 | "acosh",
138 | "asinh",
139 | "atanh",
140 | "factorial",
141 | "eint",
142 | "li2",
143 | "gamma",
144 | "gamma_inc",
145 | "lngamma",
146 | "lgamma",
147 | "digamma",
148 | "beta",
149 | "zeta",
150 | "zeta_ui",
151 | "erf",
152 | "erfc",
153 | "j0",
154 | "j1",
155 | "jn",
156 | "y0",
157 | "y1",
158 | "yn",
159 | "fma",
160 | "fms",
161 | "fmma",
162 | "fmms",
163 | "agm",
164 | "hypot",
165 | "ai",
166 | "const_log2",
167 | "const_pi",
168 | "const_euler",
169 | "const_catalan",
170 | "sum",
171 | # 5.10 Integer and Remainder Related Functions
172 | "ceil",
173 | "floor",
174 | "round",
175 | "roundeven",
176 | "trunc",
177 | "frac",
178 | "fmod",
179 | "remainder",
180 | "is_integer",
181 | # 5.12 Miscellaneous Functions
182 | "min",
183 | "max",
184 | "is_negative",
185 | "copysign",
186 | "MPFR_VERSION",
187 | "MPFR_VERSION_MAJOR",
188 | "MPFR_VERSION_MINOR",
189 | "MPFR_VERSION_PATCHLEVEL",
190 | "MPFR_VERSION_STRING",
191 | ]
192 |
193 | from bigfloat.core import (
194 | BigFloat,
195 | EMIN_MIN,
196 | EMIN_MAX,
197 | EMAX_MIN,
198 | EMAX_MAX,
199 | PRECISION_MIN,
200 | PRECISION_MAX,
201 | Inexact,
202 | Overflow,
203 | ZeroDivision,
204 | NanFlag,
205 | Underflow,
206 | set_flagstate,
207 | get_flagstate,
208 | test_flag,
209 | set_flag,
210 | clear_flag,
211 | # Miscellaneous functions
212 | next_down,
213 | next_up,
214 | # 5.2 Assignment Functions
215 | pos,
216 | # 5.4 Conversion Functions
217 | frexp,
218 | # 5.5 Basic Arithmetic Functions
219 | add,
220 | sub,
221 | mul,
222 | sqr,
223 | div,
224 | sqrt,
225 | rec_sqrt,
226 | cbrt,
227 | root,
228 | rootn,
229 | pow,
230 | neg,
231 | abs,
232 | dim,
233 | # Additional arithmetic functions (not implemented directly by MPFR)
234 | floordiv,
235 | mod,
236 | # 5.6 Comparison Functions
237 | cmp,
238 | cmpabs,
239 | is_nan,
240 | is_inf,
241 | is_finite,
242 | is_zero,
243 | is_regular,
244 | sgn,
245 | greater,
246 | greaterequal,
247 | less,
248 | lessequal,
249 | equal,
250 | notequal,
251 | lessgreater,
252 | unordered,
253 | # 5.7 Special Functions
254 | log,
255 | log2,
256 | log10,
257 | log1p,
258 | exp,
259 | exp2,
260 | exp10,
261 | expm1,
262 | cos,
263 | sin,
264 | tan,
265 | sec,
266 | csc,
267 | cot,
268 | acos,
269 | asin,
270 | atan,
271 | atan2,
272 | cosh,
273 | sinh,
274 | tanh,
275 | sech,
276 | csch,
277 | coth,
278 | acosh,
279 | asinh,
280 | atanh,
281 | factorial,
282 | eint,
283 | li2,
284 | gamma,
285 | gamma_inc,
286 | lngamma,
287 | lgamma,
288 | digamma,
289 | beta,
290 | zeta,
291 | zeta_ui,
292 | erf,
293 | erfc,
294 | j0,
295 | j1,
296 | jn,
297 | y0,
298 | y1,
299 | yn,
300 | fma,
301 | fms,
302 | fmma,
303 | fmms,
304 | agm,
305 | hypot,
306 | ai,
307 | const_log2,
308 | const_pi,
309 | const_euler,
310 | const_catalan,
311 | sum,
312 | # 5.10 Integer and Remainder Related Functions
313 | ceil,
314 | floor,
315 | round,
316 | roundeven,
317 | trunc,
318 | frac,
319 | fmod,
320 | remainder,
321 | is_integer,
322 | # 5.12 Miscellaneous Functions
323 | min,
324 | max,
325 | is_negative,
326 | copysign,
327 | )
328 |
329 | from bigfloat.version import __version__
330 |
331 | from mpfr import (
332 | # MPFR Version information
333 | MPFR_VERSION,
334 | MPFR_VERSION_MAJOR,
335 | MPFR_VERSION_MINOR,
336 | MPFR_VERSION_PATCHLEVEL,
337 | MPFR_VERSION_STRING,
338 | )
339 |
340 | from bigfloat.context import (
341 | Context,
342 | setcontext,
343 | getcontext,
344 | DefaultContext,
345 | EmptyContext,
346 | precision,
347 | rounding,
348 | extra_precision,
349 | RoundTiesToEven,
350 | RoundTowardZero,
351 | RoundTowardPositive,
352 | RoundTowardNegative,
353 | RoundAwayFromZero,
354 | )
355 |
356 | from bigfloat.ieee import (
357 | IEEEContext,
358 | half_precision,
359 | single_precision,
360 | double_precision,
361 | quadruple_precision,
362 | )
363 |
364 | from bigfloat.rounding_mode import (
365 | ROUND_TIES_TO_EVEN,
366 | ROUND_TOWARD_ZERO,
367 | ROUND_TOWARD_POSITIVE,
368 | ROUND_TOWARD_NEGATIVE,
369 | ROUND_AWAY_FROM_ZERO,
370 | )
371 |
--------------------------------------------------------------------------------
/COPYING.LESSER:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/CHANGELOG.rst:
--------------------------------------------------------------------------------
1 | What's new in bigfloat 0.4.0?
2 | =============================
3 |
4 | Release date: 2019-12-30
5 |
6 | This minor release adds a number of small features, changes the default
7 | context to match IEEE 754 quadruple precision (binary128), and fixes support
8 | for recent Python versions.
9 |
10 | Thanks to Hugo van Kemenade for contributions to this release.
11 |
12 | New Features
13 | ------------
14 |
15 | - Wrap mpfr_buildopt_gmpinternals_p and mpfr_buildopt_tune_case. (#54)
16 |
17 | - Add bigfloat.__version__ (#46).
18 |
19 | - Add bigfloat.notequal. (#47)
20 |
21 | - Add format support. (#58).
22 |
23 | - Add support for ``round``, ``math.floor``, ``math.ceil``, ``math.trunc`` on
24 | Python 3. (#64)
25 |
26 | - Add support for ``divmod`` and the ``//`` operator. (#69)
27 |
28 | - New ``floordiv`` and ``mod`` functions. The new ``mod`` replaces the old
29 | ``mod`` function, which has been renamed to ``fmod``. (#69)
30 |
31 | Changes
32 | -------
33 |
34 | - The default context now matches IEEE 754 quadruple precision instead
35 | of double precision. (#72, #89, #87)
36 |
37 | - Infinities and NaNs are now represented as 'inf' and 'nan' rather
38 | than 'Infinity' and 'NaN', for consistency with the float type, and
39 | for consistency with the newly-introduced string formatting.
40 |
41 | - The 'mod' function now follows Python sign conventions; the old
42 | 'mod' function has been renamed to 'fmod'. The '%' operator
43 | now also follows Python sign conventions. (#69)
44 |
45 | - MPFR version 3.0.0 or later is required.
46 |
47 | - Support for Python versions earlier than 3.5 or 2.7 has been dropped.
48 | Support for Python 3.7 and 3.8 has been added. (#75, 81).
49 |
50 | Bugfixes
51 | --------
52 |
53 | - The ``root`` function was accidentally wrapping ``cbrt`` (#60).
54 | Now fixed (#62).
55 |
56 | - Fix a test failure with Mpfr 4.0, that was due a change in the value
57 | of ``MPFR_PREC_MIN``. (#77)
58 |
59 | - Fix initialization of the context on background threads. (#91)
60 |
61 | - Fix unit tests that changed the context and didn't reset their changes.
62 | (#92, #98)
63 |
64 | Build
65 | -----
66 |
67 | - Use ``language_level=3`` in the Cython code. (#96)
68 |
69 | Documentation
70 | -------------
71 |
72 | - Installation documentation cleaned up. (#68)
73 |
74 | - Add ``cmp`` to list of shadowed builtins in ``README.rst``. (#63)
75 |
76 | - Fix (outdated) uses of strings for rounding modes. (#57)
77 |
78 |
79 | What's new in bigfloat 0.3.0?
80 | =============================
81 |
82 | Library
83 | -------
84 |
85 | - Fix string-returning functions and string constants in ``mpfr`` module to
86 | return something of type ``str`` both on Python 2 and Python 3. In earlier
87 | 0.3.0 pre-releases, objects of type ``unicode`` were being returned on
88 | Python 2.
89 |
90 | - Declarations in ``cmpfr.pxd`` fixed to include ``const`` where necessary;
91 | this fixes some compiler warnings.
92 |
93 | - Improved tests for hashing.
94 |
95 |
96 | Miscellaneous
97 | -------------
98 |
99 | - Fix documentation link for PyPI upload.
100 |
101 | - Docs updated to remove outdated instructions about use under Python 2.5 and
102 | outdated information (dating from the earlier ctypes version) about runtime
103 | location of the MPFR and GMP libraries.
104 |
105 | - ``README``, ``setup.py`` updates: include the quick tour in the ``README``,
106 | make content match that of the ``setup.py`` long description.
107 |
108 | - ``CHANGELOG``, ``README``, ``INSTALL`` files updated with various
109 | reStructuredText fixes; renamed to add ``.rst`` suffix so that they display
110 | nicely on GitHub.
111 |
112 | - Update copyright notices.
113 |
114 |
115 | What's new in bigfloat 0.3.0b1?
116 | ===============================
117 |
118 | Library
119 | -------
120 |
121 | - Python 3.2 and later are now supported. Python 2 support requires Python 2.6
122 | or later.
123 |
124 | - Added support for the new 'divide-by-zero' flag (exposed as ``ZeroDivision``
125 | to bigfloat).
126 |
127 | Miscellaneous
128 | -------------
129 |
130 | - Development moved from bitbucket (https://bitbucket.org/dickinsm/bigfloat)
131 | to GitHub (https://github.com/mdickinson/bigfloat), and repository
132 | converted from mercurial to Git.
133 |
134 | - Travis CI and Read the Docs GitHub hooks added.
135 |
136 |
137 | What's new in bigfloat 0.3.0a2?
138 | ===============================
139 |
140 | - Minor documentation fixes.
141 |
142 |
143 | What's new in bigfloat 0.3.0a1?
144 | ===============================
145 |
146 |
147 | Prerequisites
148 | -------------
149 |
150 | - For now, Python 2.7 and MPFR version >= 3.0 are required. Support for
151 | earlier versions of Python is planned. Support for MPFR 2.x will probably
152 | not be added.
153 |
154 |
155 | Library
156 | -------
157 |
158 | - Major rewrite and restructuring of the core code. The core now uses Cython
159 | rather than ctypes.
160 |
161 | - mpfr module now separately available as an extension type, with semantics
162 | very close to the Mpfr library.
163 |
164 | - Added bigfloat support for new rounding mode MPFR_RNDA (round away from
165 | zero).
166 |
167 | - Rounding modes are now represented as named integers (instances of
168 | RoundingMode, an int subclass), rather than strings. This allows them to be
169 | passed directly to Mpfr functions.
170 |
171 | - Fixed a bug that meant old context wasn't restored when changing exponents
172 | with one valid exponent and one invalid. (eminmax)
173 |
174 | - Many more docstrings than originally; better function signatures.
175 |
176 | - Restructured bigfloat package: mpfr wrapper module is now bigfloat.mpfr,
177 | context class and related functions are in bigfloat.context, rounding modes
178 | are defined in bigfloat.rounding_modes, and the main BigFloat type is defined
179 | in bigfloat.core. Everything is importable directory from bigfloat, as
180 | before.
181 |
182 |
183 | Documentation
184 | -------------
185 |
186 | - Most of the documentation is now generated automatically using Sphinx's
187 | autodoc extension.
188 |
189 |
190 | What's new in bigfloat 0.2.1?
191 | =============================
192 |
193 | Library
194 | -------
195 |
196 | - Simplify weakref callback scheme used to ensure BigFloat instances
197 | are freed properly.
198 |
199 | - Make sure all python files in distribution have the LGPL header.
200 |
201 |
202 | What's new in bigfloat 0.2?
203 | ===========================
204 |
205 | Library
206 | -------
207 |
208 | - The setup.py file no longer attempts to locate the MPFR library at
209 | install time. The configuration file still exists, and can be edited
210 | to give a hard-coded location. Alternatively, ctypes should find the
211 | library if it's within the usual library search paths. (If not, it
212 | might be necessary to set LD_LIBRARY_PATH or DYLD_LIBRARY_PATH.)
213 |
214 | - Use a weakref callback to ensure ``mpfr_clear`` gets called, instead of
215 | relying on ``__del__``.
216 |
217 | - Make bigfloat compatible with versions of MPFR as far back as MPFR 2.3.0
218 |
219 | - Relicense under LGPL, since this package might be considered a
220 | derived work of MPFR.
221 |
222 |
223 | Tests
224 | -----
225 |
226 | - Skip the hashing consistency tests (those that test whether ``hash(n) ==
227 | hash(BigFloat(n))`` for integers ``n``) on Python 2.5. In rare cases, this
228 | equality fails with Python 2.5, and this is awkward to fix. If this affects
229 | you, upgrade to Python 2.6 or avoid mixing BigFloat instances with ints in
230 | sets or dictionary keys.
231 |
232 |
233 | What's new in bigfloat 0.1.2?
234 | =============================
235 |
236 | Library
237 | -------
238 |
239 | - Make ``Context`` objects hashable.
240 |
241 | Documentation
242 | -------------
243 |
244 | - Add 'where to get it' section to the documentation, pointing both
245 | to the PyPI page and the bitbucket source.
246 |
247 | - Expand installation information in documentation.
248 |
249 | Packaging/distribution
250 | ----------------------
251 |
252 | - Include html documentation in distribution, in docs directory.
253 |
254 | - Include INSTALL and CHANGELOG files in distribution.
255 |
256 | - Make sure the bigfloat_config.py file ends up in the top-level
257 | package directory.
258 |
259 | - Add /usr/lib{32,64} and /usr/local/lib{32,64} to default search
260 | paths in setup.py.
261 |
--------------------------------------------------------------------------------
/bigfloat/mpfr_supplemental.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8
2 |
3 | # Copyright 2009--2019 Mark Dickinson.
4 | #
5 | # This file is part of the bigfloat package.
6 | #
7 | # The bigfloat package is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU Lesser General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or (at your
10 | # option) any later version.
11 | #
12 | # The bigfloat package is distributed in the hope that it will be useful, but
13 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 | # for more details.
16 | #
17 | # You should have received a copy of the GNU Lesser General Public License
18 | # along with the bigfloat package. If not, see .
19 | """
20 | Supplementary functions with a similar API to those in the mpfr module.
21 | """
22 | import mpfr
23 |
24 |
25 | def _quotient_exponent(x, y):
26 | """
27 | Given two positive finite MPFR instances x and y,
28 | find the exponent of x / y; that is, the unique
29 | integer e such that 2**(e-1) <= x / y < 2**e.
30 |
31 | """
32 | assert mpfr.mpfr_regular_p(x)
33 | assert mpfr.mpfr_regular_p(y)
34 |
35 | # Make copy of x with the exponent of y.
36 | x2 = mpfr.Mpfr_t()
37 | mpfr.mpfr_init2(x2, mpfr.mpfr_get_prec(x))
38 | mpfr.mpfr_set(x2, x, mpfr.MPFR_RNDN)
39 | mpfr.mpfr_set_exp(x2, mpfr.mpfr_get_exp(y))
40 |
41 | # Compare x2 and y, disregarding the sign.
42 | extra = mpfr.mpfr_cmpabs(x2, y) >= 0
43 | return extra + mpfr.mpfr_get_exp(x) - mpfr.mpfr_get_exp(y)
44 |
45 |
46 | def mpfr_floordiv(rop, x, y, rnd):
47 | """
48 | Given two MPFR numbers x and y, compute floor(x / y),
49 | rounded if necessary using the given rounding mode.
50 | The result is placed in 'rop'.
51 | """
52 | # Algorithm notes
53 | # ---------------
54 | # A simple and obvious approach is to compute floor(x / y) exactly, and
55 | # then round to the nearest representable value using the given rounding
56 | # mode. This requires computing x / y to a precision sufficient to ensure
57 | # that floor(x / y) is exactly representable. If abs(x / y) < 2**r, then
58 | # abs(floor(x / y)) <= 2**r, and so r bits of precision is enough.
59 | # However, for large quotients this is impractical, and we need some other
60 | # method. For x / y sufficiently large, it's possible to show that x / y
61 | # and floor(x / y) are indistinguishable, in the sense that both quantities
62 | # round to the same value. More precisely, we have the following theorem:
63 | #
64 | # Theorem. Suppose that x and y are nonzero finite binary floats
65 | # representable with p and q bits of precision, respectively. Let R be any
66 | # of the IEEE 754 standard rounding modes, and choose a target precision r.
67 | # Write rnd for the rounding operation from Q to precision-r binary floats
68 | # with rounding mode R. Write bin(x) for the binade of a nonzero float x.
69 | #
70 | # If R is a round-to-nearest rounding mode, and either
71 | #
72 | # (1) p <= q + r and |x / y| >= 2^(q + r), or
73 | # (2) p > q + r and bin(x) - bin(y) >= p
74 | #
75 | # then
76 | #
77 | # rnd(floor(x / y)) == rnd(x / y)
78 | #
79 | # Conversely, if R is a directed rounding mode, and either
80 | #
81 | # (1) p < q + r and |x / y| >= 2^(q + r - 1), or
82 | # (2) p >= q + r and bin(x) - bin(y) >= p
83 | #
84 | # then again
85 | #
86 | # rnd(floor(x / y)) == rnd(x / y).
87 | #
88 | # Proof. See separate notes and Coq proof in the float-proofs
89 | # repository.
90 | #
91 | # Rather than distinguish between the various cases (R directed
92 | # or not, p large versus p small) above, we use a weaker but
93 | # simpler amalgamation of the above result:
94 | #
95 | # Corollary 1. With x, y, p, q, R, r and rnd as above, if
96 | #
97 | # |x / y| >= 2^max(q + r, p)
98 | #
99 | # then
100 | #
101 | # rnd(floor(x / y)) == rnd(x / y).
102 | #
103 | # Proof. Note that |x / y| >= 2^p implies bin(x) - bin(y) >= p,
104 | # so it's enough that |x / y| >= 2^max(p, q + r) in the case of
105 | # a round-to-nearest mode, and that |x / y| >= 2^max(p, q + r - 1)
106 | # in the case of a directed rounding mode.
107 |
108 | # In special cases, it's safe to defer to mpfr_div: the result in
109 | # these cases is always 0, infinity, or nan.
110 | if not mpfr.mpfr_regular_p(x) or not mpfr.mpfr_regular_p(y):
111 | return mpfr.mpfr_div(rop, x, y, rnd)
112 |
113 | e = _quotient_exponent(x, y)
114 |
115 | p = mpfr.mpfr_get_prec(x)
116 | q = mpfr.mpfr_get_prec(y)
117 | r = mpfr.mpfr_get_prec(rop)
118 |
119 | # If e - 1 >= max(p, q+r) then |x / y| >= 2^(e-1) >= 2^max(p, q+r),
120 | # so by the above theorem, round(floordiv(x, y)) == round(div(x, y)).
121 | if e - 1 >= max(p, q + r):
122 | return mpfr.mpfr_div(rop, x, y, rnd)
123 |
124 | # Slow version: compute to sufficient bits to get integer precision. Given
125 | # that 2**(e-1) <= x / y < 2**e, need >= e bits of precision.
126 | z_prec = max(e, 2)
127 | z = mpfr.Mpfr_t()
128 | mpfr.mpfr_init2(z, z_prec)
129 |
130 | # Compute the floor exactly. The division may set the
131 | # inexact flag, so we save its state first.
132 | old_inexact = mpfr.mpfr_inexflag_p()
133 | mpfr.mpfr_div(z, x, y, mpfr.MPFR_RNDD)
134 | if not old_inexact:
135 | mpfr.mpfr_clear_inexflag()
136 |
137 | # Floor result should be exactly representable, so any rounding mode will
138 | # do.
139 | ternary = mpfr.mpfr_rint_floor(z, z, rnd)
140 | assert ternary == 0
141 |
142 | # ... and round to the given rounding mode.
143 | return mpfr.mpfr_set(rop, z, rnd)
144 |
145 |
146 | def mpfr_mod(rop, x, y, rnd):
147 | """
148 | Given two MPRF numbers x and y, compute
149 | x - floor(x / y) * y, rounded if necessary using the given
150 | rounding mode. The result is placed in 'rop'.
151 |
152 | This is the 'remainder' operation, with sign convention
153 | compatible with Python's % operator (where x % y has
154 | the same sign as y).
155 | """
156 | # There are various cases:
157 | #
158 | # 0. If either argument is a NaN, the result is NaN.
159 | #
160 | # 1. If x is infinite or y is zero, the result is NaN.
161 | #
162 | # 2. If y is infinite, return 0 with the sign of y if x is zero, x if x has
163 | # the same sign as y, and infinity with the sign of y if it has the
164 | # opposite sign.
165 | #
166 | # 3. If none of the above cases apply then both x and y are finite,
167 | # and y is nonzero. If x and y have the same sign, simply
168 | # return the result of fmod(x, y).
169 | #
170 | # 4. Now both x and y are finite, y is nonzero, and x and y have
171 | # differing signs. Compute r = fmod(x, y) with sufficient precision
172 | # to get an exact result. If r == 0, return 0 with the sign of y
173 | # (which will be the opposite of the sign of x). If r != 0,
174 | # return r + y, rounded appropriately.
175 |
176 | if not mpfr.mpfr_number_p(x) or mpfr.mpfr_nan_p(y) or mpfr.mpfr_zero_p(y):
177 | return mpfr.mpfr_fmod(rop, x, y, rnd)
178 | elif mpfr.mpfr_inf_p(y):
179 | x_negative = mpfr.mpfr_signbit(x)
180 | y_negative = mpfr.mpfr_signbit(y)
181 | if mpfr.mpfr_zero_p(x):
182 | mpfr.mpfr_set_zero(rop, -y_negative)
183 | return 0
184 | elif x_negative == y_negative:
185 | return mpfr.mpfr_set(rop, x, rnd)
186 | else:
187 | mpfr.mpfr_set_inf(rop, -y_negative)
188 | return 0
189 |
190 | x_negative = mpfr.mpfr_signbit(x)
191 | y_negative = mpfr.mpfr_signbit(y)
192 | if x_negative == y_negative:
193 | return mpfr.mpfr_fmod(rop, x, y, rnd)
194 | else:
195 | p = max(mpfr.mpfr_get_prec(x), mpfr.mpfr_get_prec(y))
196 | z = mpfr.Mpfr_t()
197 | mpfr.mpfr_init2(z, p)
198 | # Doesn't matter what rounding mode we use here; the result
199 | # should be exact.
200 | ternary = mpfr.mpfr_fmod(z, x, y, rnd)
201 | assert ternary == 0
202 | if mpfr.mpfr_zero_p(z):
203 | mpfr.mpfr_set_zero(rop, -y_negative)
204 | return 0
205 | else:
206 | return mpfr.mpfr_add(rop, y, z, rnd)
207 |
--------------------------------------------------------------------------------
/bigfloat/test/test_data/floordiv.bft:
--------------------------------------------------------------------------------
1 | context double_precision
2 | context RoundTiesToEven
3 |
4 | # Simple cases.
5 | floordiv 0x2p0 0x1p0 -> 0x2p0
6 | floordiv 0x1p0 0x2p0 -> 0x0p0
7 |
8 | # Negative operands.
9 | floordiv -0x2p0 0x1p0 -> -0x2p0
10 | floordiv -0x1p0 0x2p0 -> -0x1p0
11 |
12 | floordiv 0x2p0 -0x1p0 -> -0x2p0
13 | floordiv 0x1p0 -0x2p0 -> -0x1p0
14 |
15 | # Zeros.
16 | floordiv 0x0p0 0x1.88p0 -> 0x0p0
17 | floordiv -0x0p0 0x1.88p0 -> -0x0p0
18 | floordiv 0x0p0 -0x1.88p0 -> -0x0p0
19 | floordiv -0x0p0 -0x1.88p0 -> 0x0p0
20 |
21 | floordiv 0x1.88p0 0x0p0 -> inf ZeroDivision
22 | floordiv -0x1.88p0 0x0p0 -> -inf ZeroDivision
23 | floordiv 0x1.88p0 -0x0p0 -> -inf ZeroDivision
24 | floordiv -0x1.88p0 -0x0p0 -> inf ZeroDivision
25 |
26 | floordiv 0x0p0 0x0p0 -> nan NanFlag
27 | floordiv -0x0p0 0x0p0 -> nan NanFlag
28 | floordiv 0x0p0 -0x0p0 -> nan NanFlag
29 | floordiv -0x0p0 -0x0p0 -> nan NanFlag
30 |
31 | # Infinities.
32 | floordiv 0x0p0 inf -> 0x0p0
33 | floordiv -0x0p0 inf -> -0x0p0
34 | floordiv 0x0p0 -inf -> -0x0p0
35 | floordiv -0x0p0 -inf -> 0x0p0
36 |
37 | floordiv 0x1.34ap-23 inf -> 0x0p0
38 | floordiv -0x1.34ap-23 inf -> -0x0p0
39 | floordiv 0x1.34ap-23 -inf -> -0x0p0
40 | floordiv -0x1.34ap-23 -inf -> 0x0p0
41 |
42 | floordiv inf inf -> nan NanFlag
43 | floordiv -inf inf -> nan NanFlag
44 | floordiv inf -inf -> nan NanFlag
45 | floordiv -inf -inf -> nan NanFlag
46 |
47 | floordiv inf 0x1.adep55 -> inf
48 | floordiv -inf 0x1.adep55 -> -inf
49 | floordiv inf -0x1.adep55 -> -inf
50 | floordiv -inf -0x1.adep55 -> inf
51 |
52 | floordiv inf 0x0p0 -> inf
53 | floordiv -inf 0x0p0 -> -inf
54 | floordiv inf -0x0p0 -> -inf
55 | floordiv -inf -0x0p0 -> inf
56 |
57 | # NaNs
58 | floordiv nan 0x0p0 -> nan NanFlag
59 | floordiv nan 0x1p0 -> nan NanFlag
60 | floordiv nan inf -> nan NanFlag
61 | floordiv nan nan -> nan NanFlag
62 | floordiv inf nan -> nan NanFlag
63 | floordiv 0x1p0 nan -> nan NanFlag
64 | floordiv 0x0p0 nan -> nan NanFlag
65 |
66 | # A few randomly-generated cases.
67 | floordiv 0x1.b2a98bbcc49b4p+98 0x1.3d74b2d390501p+48 -> 0x1.5e843fc46ffa8p+50
68 | floordiv -0x1.b2a98bbcc49b4p+98 -0x1.3d74b2d390501p+48 -> 0x1.5e843fc46ffa8p+50
69 | floordiv -0x1.b2a98bbcc49b4p+98 0x1.3d74b2d390501p+48 -> -0x1.5e843fc46ffacp+50
70 | floordiv 0x1.b2a98bbcc49b4p+98 -0x1.3d74b2d390501p+48 -> -0x1.5e843fc46ffacp+50
71 |
72 | # Randomly-generated near-halfway cases.
73 | floordiv 0x1.7455b4855c470p+158 0x1.9f63221b65037p+52 -> 0x1.caef27bbd32c3p+105 Inexact
74 | floordiv -0x1.7455b4855c470p+158 0x1.9f63221b65037p+52 -> -0x1.caef27bbd32c4p+105 Inexact
75 | floordiv 0x1.3e80b2f3da4e3p+158 0x1.55d84f1af57e3p+52 -> 0x1.dd0a000b852e5p+105 Inexact
76 | floordiv -0x1.3e80b2f3da4e3p+158 0x1.55d84f1af57e3p+52 -> -0x1.dd0a000b852e6p+105 Inexact
77 | floordiv 0x1.1ef2d934ebab9p+158 0x1.b1f7b86b3147fp+52 -> 0x1.528b96ac455bfp+105 Inexact
78 | floordiv -0x1.1ef2d934ebab9p+158 0x1.b1f7b86b3147fp+52 -> -0x1.528b96ac455c0p+105 Inexact
79 | floordiv 0x1.d9e46ba382852p+158 0x1.e12e2c5c55f27p+52 -> 0x1.f83ebede8104bp+105 Inexact
80 | floordiv -0x1.d9e46ba382852p+158 0x1.e12e2c5c55f27p+52 -> -0x1.f83ebede8104cp+105 Inexact
81 | floordiv 0x1.0a29a5b5b8f7dp+158 0x1.2c53d755c382dp+52 -> 0x1.c5c170a956bd2p+105 Inexact
82 | floordiv -0x1.0a29a5b5b8f7dp+158 0x1.2c53d755c382dp+52 -> -0x1.c5c170a956bd2p+105 Inexact
83 | floordiv 0x1.236ba96f8838bp+158 0x1.e2e23e8730f95p+52 -> 0x1.34fe01ad9e1dep+105 Inexact
84 | floordiv -0x1.236ba96f8838bp+158 0x1.e2e23e8730f95p+52 -> -0x1.34fe01ad9e1dep+105 Inexact
85 | floordiv 0x1.1ff3215dc95f4p+158 0x1.ec809f7a6c20bp+52 -> 0x1.2b596bfcd1cd1p+105 Inexact
86 | floordiv -0x1.1ff3215dc95f4p+158 0x1.ec809f7a6c20bp+52 -> -0x1.2b596bfcd1cd2p+105 Inexact
87 | floordiv 0x1.b55d8ec0da9fep+158 0x1.f6d8adea89b9fp+52 -> 0x1.bd53bacf4e02fp+105 Inexact
88 | floordiv -0x1.b55d8ec0da9fep+158 0x1.f6d8adea89b9fp+52 -> -0x1.bd53bacf4e030p+105 Inexact
89 | floordiv 0x1.2852761e5852bp+158 0x1.7ddb08bf86a6fp+52 -> 0x1.8d509db211a47p+105 Inexact
90 | floordiv -0x1.2852761e5852bp+158 0x1.7ddb08bf86a6fp+52 -> -0x1.8d509db211a48p+105 Inexact
91 | floordiv 0x1.1c97fd65f4e7cp+158 0x1.a6ba81f4da293p+52 -> 0x1.58b1a7e0e65cdp+105 Inexact
92 | floordiv -0x1.1c97fd65f4e7cp+158 0x1.a6ba81f4da293p+52 -> -0x1.58b1a7e0e65cep+105 Inexact
93 |
94 | floordiv 0x1.8ae6742f94fcap+158 0x1.af61efd069439p+52 -> 0x1.d4b323e4872fcp+105 Inexact
95 | floordiv -0x1.8ae6742f94fcap+158 0x1.af61efd069439p+52 -> -0x1.d4b323e4872fcp+105 Inexact
96 | floordiv 0x1.50371bfb1ded8p+158 0x1.64df147fa2c0bp+52 -> 0x1.e25d6618d002ep+105 Inexact
97 | floordiv -0x1.50371bfb1ded8p+158 0x1.64df147fa2c0bp+52 -> -0x1.e25d6618d002fp+105 Inexact
98 | floordiv 0x1.29ad82f921e61p+158 0x1.ee88b9d5af47fp+52 -> 0x1.3430ee7ff9a40p+105 Inexact
99 | floordiv -0x1.29ad82f921e61p+158 0x1.ee88b9d5af47fp+52 -> -0x1.3430ee7ff9a41p+105 Inexact
100 | floordiv 0x1.341e592b2ef12p+158 0x1.c5715b0058be3p+52 -> 0x1.5be8a10c7f71ap+105 Inexact
101 | floordiv -0x1.341e592b2ef12p+158 0x1.c5715b0058be3p+52 -> -0x1.5be8a10c7f71bp+105 Inexact
102 | floordiv 0x1.281ad0d0b6e5ap+158 0x1.84ad50291a943p+52 -> 0x1.860e39fb7ea4ap+105 Inexact
103 | floordiv -0x1.281ad0d0b6e5ap+158 0x1.84ad50291a943p+52 -> -0x1.860e39fb7ea4bp+105 Inexact
104 | floordiv 0x1.1016dc07e1acep+158 0x1.70c44c2b976c1p+52 -> 0x1.79c5994d7f360p+105 Inexact
105 | floordiv -0x1.1016dc07e1acep+158 0x1.70c44c2b976c1p+52 -> -0x1.79c5994d7f360p+105 Inexact
106 | floordiv 0x1.c348cf5e24425p+158 0x1.d34d5e92de493p+52 -> 0x1.ee73382469332p+105 Inexact
107 | floordiv -0x1.c348cf5e24425p+158 0x1.d34d5e92de493p+52 -> -0x1.ee73382469333p+105 Inexact
108 | floordiv 0x1.bcfea94be48e6p+158 0x1.dde69c1267a85p+52 -> 0x1.dcbefc6ebc8dap+105 Inexact
109 | floordiv -0x1.bcfea94be48e6p+158 0x1.dde69c1267a85p+52 -> -0x1.dcbefc6ebc8dap+105 Inexact
110 |
111 | # Some cases where Python's // on floats gets the wrong result.
112 | floordiv 0x1.0e31636b07d9dp-898 0x1.c68968514f16bp-954 -> 0x1.3059e434dd2bep+55 Inexact
113 | floordiv 0x1.2bb44bbf6a807p-537 0x1.94a4d2cd73882p-589 -> 0x1.7b3809b6af846p+51
114 |
115 | # Overflow and underflow. (The latter shouldn't be possible unless
116 | # emin >= 0, which we currently don't check.)
117 | floordiv 0x1p1000 0x1p-1000 -> Infinity Inexact Overflow
118 | floordiv 0x1p512 0x1p-512 -> Infinity Inexact Overflow
119 | floordiv 0x1p511 0x1p-512 -> 0x1p1023
120 | floordiv 0x1p-1000 0x1p1000 -> 0x0p0
121 |
122 | # An extreme case where the floor of the quotient is exactly
123 | # representable but the quotient is not.
124 | floordiv 0x1.ff2e8e6fb6a62p+157 0x1.ff973c8000001p+52 -> 0x1.ff973c7ffffffp+104
125 | floordiv -0x1.ff2e8e6fb6a62p+157 0x1.ff973c8000001p+52 -> -0x1.ff973c7ffffffp+104 Inexact
126 | # ... and where neither are.
127 | floordiv 0x1.ff2e8e6fb6a62p+158 0x1.ff973c8000001p+52 -> 0x1.ff973c7ffffffp+105 Inexact
128 | floordiv -0x1.ff2e8e6fb6a62p+158 0x1.ff973c8000001p+52 -> -0x1.ff973c7ffffffp+105 Inexact
129 |
130 | #### Halfway cases: exact quotient is within 1 of a halfway case.
131 | # Exact quotient is 0x1.b6cb791cacbf37ffffffffffffb6de167b388b7fc8b3666a53bb....p+105
132 | # floordiv result is 1 smaller than halfway case, rounds down (towards zero)
133 | floordiv 0x1.800000000003bp+158 0x1.c0104a4a58bd7p+52 -> 0x1.b6cb791cacbf3p+105 Inexact
134 | # floordiv result *is* halfway case, rounds down (away from zero)
135 | floordiv -0x1.800000000003bp+158 0x1.c0104a4a58bd7p+52 -> -0x1.b6cb791cacbf4p+105 Inexact
136 |
137 | # Exact quotient is 0x1.98aa85ad41b278000000000000441c6b9ce0480bae415da0f245....p+105
138 | # floordiv result *is* halfway case, rounds up (away from zero)
139 | floordiv 0x1.8000000000021p+158 0x1.e118cf408df51p+52 -> 0x1.98aa85ad41b28p+105 Inexact
140 | # floordiv result one smaller than halfway case; rounds down (away from zero)
141 | floordiv -0x1.8000000000021p+158 0x1.e118cf408df51p+52 -> -0x1.98aa85ad41b28p+105 Inexact
142 |
143 |
144 | #### Check that the rounding mode is being respected.
145 | floordiv 0x1p53 0x0.fffffffffffff8p0 -> 0x1p53 Inexact
146 | floordiv 0x1p53 0x0.fffffffffffff0p0 -> 0x20000000000002p0
147 | floordiv 0x1p53 0x0.ffffffffffffe8p0 -> 0x20000000000004p0 Inexact
148 |
149 | context RoundTowardPositive
150 | floordiv 0x1p53 0x0.fffffffffffff8p0 -> 0x20000000000002p0 Inexact
151 | floordiv 0x1p53 0x0.fffffffffffff0p0 -> 0x20000000000002p0
152 | floordiv 0x1p53 0x0.ffffffffffffe8p0 -> 0x20000000000004p0 Inexact
153 | floordiv 0x1.ff2e8e6fb6a62p+157 0x1.ff973c8000001p+52 -> 0x1.ff973c7ffffffp+104
154 | floordiv -0x1.ff2e8e6fb6a62p+157 0x1.ff973c8000001p+52 -> -0x1.ff973c7ffffffp+104 Inexact
155 |
156 | context RoundTowardNegative
157 | floordiv 0x1p53 0x0.fffffffffffff8p0 -> 0x20000000000000p0 Inexact
158 | floordiv 0x1p53 0x0.fffffffffffff0p0 -> 0x20000000000002p0
159 | floordiv 0x1p53 0x0.ffffffffffffe8p0 -> 0x20000000000002p0 Inexact
160 | floordiv 0x1.ff2e8e6fb6a62p+157 0x1.ff973c8000001p+52 -> 0x1.ff973c7ffffffp+104
161 | floordiv -0x1.ff2e8e6fb6a62p+157 0x1.ff973c8000001p+52 -> -0x1.ff973c8000000p+104 Inexact
162 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8
2 |
3 | # Copyright 2009--2019 Mark Dickinson.
4 | #
5 | # This file is part of the bigfloat package.
6 | #
7 | # The bigfloat package is free software: you can redistribute it and/or modify
8 | # it under the terms of the GNU Lesser General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License, or (at your
10 | # option) any later version.
11 | #
12 | # The bigfloat package is distributed in the hope that it will be useful, but
13 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 | # for more details.
16 | #
17 | # You should have received a copy of the GNU Lesser General Public License
18 | # along with the bigfloat package. If not, see .
19 |
20 | import os
21 |
22 | from setuptools import setup, Extension
23 |
24 |
25 | DESCRIPTION = """\
26 | Arbitrary-precision correctly-rounded floating-point arithmetic, via MPFR.\
27 | """
28 |
29 | LONG_DESCRIPTION = """\
30 | The ``bigfloat`` package is a Python package providing arbitrary-precision
31 | correctly-rounded binary floating-point arithmetic. It is implemented as a
32 | `Cython `_ wrapper around the `GNU MPFR library
33 | `_. A couple of lines of Python code should give the
34 | idea::
35 |
36 | >>> from bigfloat import *
37 | >>> with precision(200) + RoundTowardZero:
38 | ... print(sqrt(2))
39 | ...
40 | 1.4142135623730950488016887242096980785696718753769480731766796
41 | >>> with quadruple_precision:
42 | ... const_pi()
43 | ...
44 | BigFloat.exact('3.14159265358979323846264338327950280', precision=113)
45 |
46 | Features
47 | --------
48 |
49 | - Supports Python 2 (version 2.7) and Python 3 (version 3.5 or later).
50 |
51 | - Exactly reproducible correctly-rounded results across platforms;
52 | precisely-defined semantics compatible with the IEEE 754-2008 standard.
53 |
54 | - Support for mixed-type operations with Python integers and floats.
55 |
56 | - Support for emulating IEEE 754 arithmetic in any of the IEEE binary
57 | interchange formats described in IEEE 754-2008. Infinities, NaNs,
58 | signed zeros, and subnormals are all supported.
59 |
60 | - Easy control of rounding modes and precisions via ``Context`` objects
61 | and Python's ``with`` statement.
62 |
63 | Documentation
64 | -------------
65 |
66 | Full `package documentation `_ is hosted at
67 | Read the Docs. Read on for a quick tour.
68 |
69 | A quick tour
70 | ------------
71 |
72 | The ``bigfloat`` package is small and simple to use. Here's a quick
73 | tour of some of its features.
74 |
75 | For demonstration purposes, start with::
76 |
77 | >>> from bigfloat import *
78 |
79 | Note that this import shadows some builtin Python functions, namely ``abs``,
80 | ``max``, ``min``, ``pow``, ``round`` and (on Python 2 only) ``cmp``. In normal
81 | usage you'll probably only want to import the classes and functions that you
82 | actually need.
83 |
84 | The main class is the ``BigFloat`` class::
85 |
86 | >>> BigFloat(1) # can be constructed from an integer, float or string
87 | BigFloat.exact('1.0000000000000000', precision=53)
88 | >>> BigFloat('3.14159') ** 2 / 6.0 # can combine with ints and floats
89 | BigFloat.exact('1.6449312880166664', precision=53)
90 | >>> BigFloat('0.1', precision(200)) # high-precision value from string
91 | BigFloat.exact('0.1000000000000000000000000000000000000000000000000000
92 | 0000000002', precision=200)
93 |
94 | Newly-created ``BigFloat`` instances refer to the current *context* to
95 | determine what precision and rounding modes to use. This current
96 | context is represented by a ``Context`` instance, and can be retrieved
97 | by calling ``getcontext``::
98 |
99 | >>> getcontext()
100 | Context(precision=53, emax=1073741823, emin=-1073741823,
101 | subnormalize=False, rounding=ROUND_TIES_TO_EVEN)
102 |
103 | The ``precision(200)`` argument passed to the ``BigFloat`` constructor
104 | above is also an example of a ``Context``::
105 |
106 | >>> precision(200)
107 | Context(precision=200)
108 |
109 | The context used for a calculation can be set using the ``setcontext``
110 | function, but a better way to make a temporary change to the context
111 | is to use Python's ``with`` statement::
112 |
113 | >>> with precision(1000):
114 | ... print sqrt(2)
115 | ...
116 | 1.41421356237309504880168872420969807856967187537694807317667973
117 | 7990732478462107038850387534327641572735013846230912297024924836
118 | 0558507372126441214970999358314132226659275055927557999505011527
119 | 8206057147010955997160597027453459686201472851741864088919860955
120 | 232923048430871432145083976260362799525140798964
121 |
122 | Here, ``sqrt`` is one of a number of mathematical functions that the
123 | ``bigfloat`` package exports. As you can see, these functions operate on
124 | integers and floats as well as ``BigFloat`` instances, but always
125 | return a ``BigFloat`` instance.
126 |
127 | Rounding modes can be controlled similarly. Here are upper and lower
128 | bounds for π, accurate to 53 significant bits::
129 |
130 | >>> with RoundTowardPositive:
131 | ... const_pi()
132 | ...
133 | BigFloat.exact('3.1415926535897936', precision=53)
134 | >>> with RoundTowardNegative:
135 | ... const_pi()
136 | ...
137 | BigFloat.exact('3.1415926535897931', precision=53)
138 |
139 | And as you'd expect, ``with`` statements like those above can be
140 | nested. ``Context`` objects can also be combined using addition::
141 |
142 | >>> with RoundTowardPositive + precision(24):
143 | ... BigFloat(1) / 3
144 | ...
145 | BigFloat.exact('0.333333343', precision=24)
146 |
147 | Various ``Context`` objects corresponding to IEEE 754 interchange
148 | formats are predefined::
149 |
150 | >>> quadruple_precision
151 | Context(precision=113, emax=16384, emin=-16493, subnormalize=True)
152 | >>> half_precision
153 | Context(precision=11, emax=16, emin=-23, subnormalize=True)
154 | >>> with half_precision:
155 | log(2)
156 | ...
157 | BigFloat.exact('0.69336', precision=11)
158 |
159 | Installation
160 | ------------
161 |
162 | The ``bigfloat`` package is `available on the Python package index
163 | `_, and can be installed in the usual
164 | way using ``easy_install`` or ``pip``. Alternatively, the development sources
165 | may be downloaded from the project's `homepage
166 | `_ on GitHub.
167 |
168 | For more comprehensive installation instructions, please see the `full
169 | documentation `_.
170 |
171 | Feedback
172 | --------
173 |
174 | Feedback is welcome! Please use the `GitHub issue tracker
175 | `_ to report issues.
176 | Alternatively, you can contact Mark Dickinson directly at dickinsm@gmail.com
177 | with suggestions, complaints, bug reports, etc.
178 |
179 | License
180 | -------
181 |
182 | The bigfloat package is copyright (C) 2009--2019 Mark Dickinson
183 |
184 | The bigfloat package is free software: you can redistribute it and/or modify
185 | it under the terms of the GNU Lesser General Public License as published by
186 | the Free Software Foundation, either version 3 of the License, or (at your
187 | option) any later version.
188 |
189 | The bigfloat package is distributed in the hope that it will be useful, but
190 | WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
191 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
192 | for more details.
193 |
194 | You should have received a copy of the GNU Lesser General Public License
195 | along with the bigfloat package. If not, see .
196 |
197 | Links
198 | -----
199 | - `Documentation at Read the Docs `_
200 | - `Python package index `_
201 | - `Project homepage at GitHub `_
202 | - `Issue tracker `_
203 | """
204 |
205 | # During package development we want to use Cython, but the distributed
206 | # egg shouldn't use Cython. We use the presence of PKG-INFO to determine
207 | # which of these is true.
208 | if os.path.exists("PKG-INFO"):
209 | USE_CYTHON = False
210 | else:
211 | USE_CYTHON = True
212 |
213 |
214 | if USE_CYTHON:
215 | from Cython.Build import cythonize
216 |
217 | extensions = cythonize(
218 | Extension("mpfr", ["mpfr.pyx"], libraries=["mpfr", "gmp"],)
219 | )
220 | else:
221 | extensions = [
222 | Extension("mpfr", ["mpfr.c"], libraries=["mpfr", "gmp"],),
223 | ]
224 |
225 |
226 | CLASSIFIERS = """\
227 | Development Status :: 4 - Beta
228 | Intended Audience :: Developers
229 | Intended Audience :: Education
230 | Intended Audience :: Science/Research
231 | License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
232 | Operating System :: OS Independent
233 | Programming Language :: Python :: 2
234 | Programming Language :: Python :: 2.7
235 | Programming Language :: Python :: 3
236 | Programming Language :: Python :: 3.5
237 | Programming Language :: Python :: 3.6
238 | Programming Language :: Python :: 3.7
239 | Programming Language :: Python :: 3.8
240 | Programming Language :: Python :: Implementation :: CPython
241 | Topic :: Scientific/Engineering :: Mathematics
242 | """.splitlines()
243 |
244 |
245 | def get_version_info():
246 | """Extract version information as a dictionary from version.py."""
247 | version_info = {}
248 | with open(os.path.join("bigfloat", "version.py"), "r") as f:
249 | version_code = compile(f.read(), "version.py", "exec")
250 | exec(version_code, version_info)
251 | return version_info
252 |
253 |
254 | version_info = get_version_info()
255 |
256 | setup(
257 | name="bigfloat",
258 | version=version_info["release"],
259 | description=DESCRIPTION,
260 | long_description=LONG_DESCRIPTION,
261 | long_description_content_type="text/x-rst",
262 | install_requires=["six"],
263 | author="Mark Dickinson",
264 | author_email="dickinsm@gmail.com",
265 | url="http://github.com/mdickinson/bigfloat",
266 | classifiers=CLASSIFIERS,
267 | platforms=["Linux", "OS X"],
268 | license="GNU Library or Lesser General Public License (LGPL)",
269 | ext_modules=extensions,
270 | packages=["bigfloat", "bigfloat.test"],
271 | package_data={"bigfloat.test": ["test_data/*.bft"]},
272 | )
273 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | #
4 | # bigfloat documentation build configuration file, created by
5 | # sphinx-quickstart on Sun Jun 29 15:53:52 2014.
6 | #
7 | # This file is execfile()d with the current directory set to its
8 | # containing dir.
9 | #
10 | # Note that not all possible configuration values are present in this
11 | # autogenerated file.
12 | #
13 | # All configuration values have a default; values that are commented out
14 | # serve to show the default.
15 |
16 | import os
17 | import sys
18 |
19 | import bigfloat.version
20 |
21 |
22 | # We need to mock out the mpfr module for the doc builds, since
23 | # Read the Docs doesn't support building extension modules.
24 | class MockMpfr(object):
25 | MPFR_RNDN = 0
26 |
27 | MPFR_RNDZ = 1
28 |
29 | MPFR_RNDU = 2
30 |
31 | MPFR_RNDD = 3
32 |
33 | MPFR_RNDA = 4
34 |
35 | MPFR_RNDF = 5
36 |
37 | MPFR_EMIN_DEFAULT = -1073741823
38 |
39 | MPFR_EMAX_DEFAULT = 1073741823
40 |
41 | MPFR_PREC_MIN = 2
42 |
43 | MPFR_PREC_MAX = 9223372036854775807
44 |
45 | Mpfr_t = object
46 |
47 | MPFR_VERSION_MAJOR = 3
48 |
49 | MPFR_VERSION_MINOR = 1
50 |
51 | def mpfr_get_emin_max(self):
52 | return 4611686018427387903
53 |
54 | def mpfr_get_emax_min(self):
55 | return -4611686018427387903
56 |
57 | def mpfr_set_emin(self, precision):
58 | pass
59 |
60 | def mpfr_set_emax(self, precision):
61 | pass
62 |
63 | def __getattr__(self, name):
64 | return None
65 |
66 |
67 | # For the doc build, replace 'mpfr' extension module with a dummy
68 | # object.
69 | sys.modules["mpfr"] = MockMpfr()
70 |
71 | # If extensions (or modules to document with autodoc) are in another directory,
72 | # add these directories to sys.path here. If the directory is relative to the
73 | # documentation root, use os.path.abspath to make it absolute, like shown here.
74 | package_dir = os.path.abspath(os.path.join(os.path.pardir, os.path.pardir))
75 | sys.path.insert(0, package_dir)
76 |
77 | # -- General configuration ------------------------------------------------
78 |
79 | # If your documentation needs a minimal Sphinx version, state it here.
80 | # needs_sphinx = '1.0'
81 |
82 | # Add any Sphinx extension module names here, as strings. They can be
83 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
84 | # ones.
85 | extensions = [
86 | "sphinx.ext.autodoc",
87 | "sphinx.ext.doctest",
88 | "sphinx.ext.intersphinx",
89 | "sphinx.ext.coverage",
90 | "sphinx.ext.mathjax",
91 | ]
92 |
93 | # Add any paths that contain templates here, relative to this directory.
94 | templates_path = ["_templates"]
95 |
96 | # The suffix of source filenames.
97 | source_suffix = ".rst"
98 |
99 | # The encoding of source files.
100 | # source_encoding = 'utf-8-sig'
101 |
102 | # The master toctree document.
103 | master_doc = "index"
104 |
105 | # General information about the project.
106 | project = "bigfloat"
107 | copyright = "2009--2019, Mark Dickinson"
108 |
109 | # The version info for the project you're documenting, acts as replacement for
110 | # |version| and |release|, also used in various other places throughout the
111 | # built documents.
112 | #
113 | # The short X.Y version.
114 | version = bigfloat.version.version
115 |
116 | # The full version, including alpha/beta/rc tags.
117 | release = bigfloat.version.release
118 |
119 | # The language for content autogenerated by Sphinx. Refer to documentation
120 | # for a list of supported languages.
121 | # language = None
122 |
123 | # There are two options for replacing |today|: either, you set today to some
124 | # non-false value, then it is used:
125 | # today = ''
126 | # Else, today_fmt is used as the format for a strftime call.
127 | # today_fmt = '%B %d, %Y'
128 |
129 | # List of patterns, relative to source directory, that match files and
130 | # directories to ignore when looking for source files.
131 | exclude_patterns = []
132 |
133 | # The reST default role (used for this markup: `text`) to use for all
134 | # documents.
135 | # default_role = None
136 |
137 | # If true, '()' will be appended to :func: etc. cross-reference text.
138 | add_function_parentheses = False
139 |
140 | # If true, the current module name will be prepended to all description
141 | # unit titles (such as .. function::).
142 | # add_module_names = True
143 |
144 | # If true, sectionauthor and moduleauthor directives will be shown in the
145 | # output. They are ignored by default.
146 | # show_authors = False
147 |
148 | # The name of the Pygments (syntax highlighting) style to use.
149 | pygments_style = "sphinx"
150 |
151 | # A list of ignored prefixes for module index sorting.
152 | # modindex_common_prefix = []
153 |
154 | # If true, keep warnings as "system message" paragraphs in the built documents.
155 | # keep_warnings = False
156 |
157 |
158 | # -- Options for HTML output ----------------------------------------------
159 |
160 | # The theme to use for HTML and HTML Help pages. See the documentation for
161 | # a list of builtin themes.
162 | html_theme = "default"
163 |
164 | # Theme options are theme-specific and customize the look and feel of a theme
165 | # further. For a list of options available for each theme, see the
166 | # documentation.
167 | # html_theme_options = {}
168 |
169 | # Add any paths that contain custom themes here, relative to this directory.
170 | # html_theme_path = []
171 |
172 | # The name for this set of Sphinx documents. If None, it defaults to
173 | # " v documentation".
174 | # html_title = None
175 |
176 | # A shorter title for the navigation bar. Default is the same as html_title.
177 | # html_short_title = None
178 |
179 | # The name of an image file (relative to this directory) to place at the top
180 | # of the sidebar.
181 | # html_logo = None
182 |
183 | # The name of an image file (within the static path) to use as favicon of the
184 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
185 | # pixels large.
186 | # html_favicon = None
187 |
188 | # Add any paths that contain custom static files (such as style sheets) here,
189 | # relative to this directory. They are copied after the builtin static files,
190 | # so a file named "default.css" will overwrite the builtin "default.css".
191 | # html_static_path = ['_static']
192 |
193 | # Add any extra paths that contain custom files (such as robots.txt or
194 | # .htaccess) here, relative to this directory. These files are copied
195 | # directly to the root of the documentation.
196 | # html_extra_path = []
197 |
198 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
199 | # using the given strftime format.
200 | # html_last_updated_fmt = '%b %d, %Y'
201 |
202 | # If true, SmartyPants will be used to convert quotes and dashes to
203 | # typographically correct entities.
204 | # html_use_smartypants = True
205 |
206 | # Custom sidebar templates, maps document names to template names.
207 | # html_sidebars = {}
208 |
209 | # Additional templates that should be rendered to pages, maps page names to
210 | # template names.
211 | # html_additional_pages = {}
212 |
213 | # If false, no module index is generated.
214 | # html_domain_indices = True
215 |
216 | # If false, no index is generated.
217 | # html_use_index = True
218 |
219 | # If true, the index is split into individual pages for each letter.
220 | # html_split_index = False
221 |
222 | # If true, links to the reST sources are added to the pages.
223 | # html_show_sourcelink = True
224 |
225 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
226 | # html_show_sphinx = True
227 |
228 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
229 | # html_show_copyright = True
230 |
231 | # If true, an OpenSearch description file will be output, and all pages will
232 | # contain a tag referring to it. The value of this option must be the
233 | # base URL from which the finished HTML is served.
234 | # html_use_opensearch = ''
235 |
236 | # This is the file name suffix for HTML files (e.g. ".xhtml").
237 | # html_file_suffix = None
238 |
239 | # Output file base name for HTML help builder.
240 | htmlhelp_basename = "bigfloatdoc"
241 |
242 |
243 | # -- Options for LaTeX output ---------------------------------------------
244 |
245 | latex_elements = {}
246 |
247 | # Grouping the document tree into LaTeX files. List of tuples
248 | # (source start file, target name, title,
249 | # author, documentclass [howto, manual, or own class]).
250 | latex_documents = [
251 | (
252 | "index",
253 | "bigfloat.tex",
254 | "bigfloat Documentation",
255 | "Mark Dickinson",
256 | "manual",
257 | ),
258 | ]
259 |
260 | # The name of an image file (relative to this directory) to place at the top of
261 | # the title page.
262 | # latex_logo = None
263 |
264 | # For "manual" documents, if this is true, then toplevel headings are parts,
265 | # not chapters.
266 | # latex_use_parts = False
267 |
268 | # If true, show page references after internal links.
269 | # latex_show_pagerefs = False
270 |
271 | # If true, show URL addresses after external links.
272 | # latex_show_urls = False
273 |
274 | # Documents to append as an appendix to all manuals.
275 | # latex_appendices = []
276 |
277 | # If false, no module index is generated.
278 | # latex_domain_indices = True
279 |
280 |
281 | # -- Options for manual page output ---------------------------------------
282 |
283 | # One entry per manual page. List of tuples
284 | # (source start file, name, description, authors, manual section).
285 | man_pages = [
286 | ("index", "bigfloat", "bigfloat Documentation", ["Mark Dickinson"], 1)
287 | ]
288 |
289 | # If true, show URL addresses after external links.
290 | # man_show_urls = False
291 |
292 |
293 | # -- Options for Texinfo output -------------------------------------------
294 |
295 | # Grouping the document tree into Texinfo files. List of tuples
296 | # (source start file, target name, title, author,
297 | # dir menu entry, description, category)
298 | texinfo_documents = [
299 | (
300 | "index",
301 | "bigfloat",
302 | "bigfloat Documentation",
303 | "Mark Dickinson",
304 | "bigfloat",
305 | "One line description of project.",
306 | "Miscellaneous",
307 | ),
308 | ]
309 |
310 | # Documents to append as an appendix to all manuals.
311 | # texinfo_appendices = []
312 |
313 | # If false, no module index is generated.
314 | # texinfo_domain_indices = True
315 |
316 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
317 | # texinfo_show_urls = 'footnote'
318 |
319 | # If true, do not generate a @detailmenu in the "Top" node's menu.
320 | # texinfo_no_detailmenu = False
321 |
322 |
323 | # Example configuration for intersphinx: refer to the Python standard library.
324 | intersphinx_mapping = {"python": ("http://docs.python.org/3/", None)}
325 |
326 |
327 | # Workaround for failing PDF build due to a Unicode minus sign.
328 | def setup(app):
329 | from sphinx.util.texescape import tex_replacements
330 |
331 | tex_replacements.append((u"\u2212", u"-"),)
332 |
--------------------------------------------------------------------------------
/bigfloat/test/test_context.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | import threading
19 | import unittest
20 |
21 | from six.moves import queue
22 |
23 | import mpfr
24 | from bigfloat.context import (
25 | getcontext,
26 | Context,
27 | DefaultContext,
28 | precision,
29 | RoundAwayFromZero,
30 | RoundTiesToEven,
31 | RoundTowardNegative,
32 | RoundTowardPositive,
33 | RoundTowardZero,
34 | _temporary_exponent_bounds,
35 | )
36 | from bigfloat.ieee import quadruple_precision
37 | from bigfloat.rounding_mode import (
38 | ROUND_TIES_TO_EVEN,
39 | ROUND_TOWARD_ZERO,
40 | ROUND_TOWARD_POSITIVE,
41 | ROUND_TOWARD_NEGATIVE,
42 | ROUND_AWAY_FROM_ZERO,
43 | )
44 |
45 | all_rounding_modes = [
46 | ROUND_TIES_TO_EVEN,
47 | ROUND_TOWARD_ZERO,
48 | ROUND_TOWARD_POSITIVE,
49 | ROUND_TOWARD_NEGATIVE,
50 | ROUND_AWAY_FROM_ZERO,
51 | ]
52 |
53 |
54 | class ContextTests(unittest.TestCase):
55 | def test__temporary_exponent_bounds(self):
56 | # Failed calls to _temporary_exponent_bounds shouldn't affect emin or
57 | # emax.
58 | original_emin = mpfr.mpfr_get_emin()
59 | original_emax = mpfr.mpfr_get_emax()
60 |
61 | # Call to _temporary_exponent_bounds should restore original values.
62 | with _temporary_exponent_bounds(-10, 10):
63 | self.assertEqual(mpfr.mpfr_get_emin(), -10)
64 | self.assertEqual(mpfr.mpfr_get_emax(), 10)
65 | self.assertEqual(mpfr.mpfr_get_emin(), original_emin)
66 | self.assertEqual(mpfr.mpfr_get_emax(), original_emax)
67 |
68 | # Even erroneous calls should restore originals.
69 | with self.assertRaises(OverflowError):
70 | with _temporary_exponent_bounds(-10, 10 ** 100):
71 | pass
72 | self.assertEqual(mpfr.mpfr_get_emin(), original_emin)
73 | self.assertEqual(mpfr.mpfr_get_emax(), original_emax)
74 |
75 | with self.assertRaises(OverflowError):
76 | with _temporary_exponent_bounds(-(10 ** 100), 10):
77 | pass
78 | self.assertEqual(mpfr.mpfr_get_emin(), original_emin)
79 | self.assertEqual(mpfr.mpfr_get_emax(), original_emax)
80 |
81 | with self.assertRaises(OverflowError):
82 | with _temporary_exponent_bounds(-(10 ** 100), 10 ** 100):
83 | pass
84 | self.assertEqual(mpfr.mpfr_get_emin(), original_emin)
85 | self.assertEqual(mpfr.mpfr_get_emax(), original_emax)
86 |
87 | def test_attributes(self):
88 | c = Context(
89 | emin=-999,
90 | emax=999,
91 | precision=100,
92 | subnormalize=True,
93 | rounding=ROUND_TIES_TO_EVEN,
94 | )
95 | self.assertIsInstance(c.precision, int)
96 | self.assertIsInstance(c.emax, int)
97 | self.assertIsInstance(c.emin, int)
98 | self.assertIsInstance(c.subnormalize, bool)
99 | self.assertIn(c.rounding, all_rounding_modes)
100 |
101 | def test_bad_rounding_mode(self):
102 | with self.assertRaises(ValueError):
103 | Context(rounding=-1)
104 |
105 | def test_default_context(self):
106 | self.assertEqual(
107 | DefaultContext, quadruple_precision + RoundTiesToEven,
108 | )
109 |
110 | def test_rounding_contexts(self):
111 | with RoundTiesToEven:
112 | self.assertEqual(getcontext().rounding, ROUND_TIES_TO_EVEN)
113 | with RoundTowardPositive:
114 | self.assertEqual(getcontext().rounding, ROUND_TOWARD_POSITIVE)
115 | with RoundTowardNegative:
116 | self.assertEqual(getcontext().rounding, ROUND_TOWARD_NEGATIVE)
117 | with RoundTiesToEven:
118 | self.assertEqual(getcontext().rounding, ROUND_TIES_TO_EVEN)
119 | with RoundAwayFromZero:
120 | self.assertEqual(getcontext().rounding, ROUND_AWAY_FROM_ZERO)
121 |
122 | # Rounding contexts should not affect existing settings for
123 | # precision, exponents, etc.
124 | original_contexts = [
125 | Context(
126 | precision=234,
127 | emin=-9999,
128 | emax=9999,
129 | subnormalize=True,
130 | rounding=ROUND_TOWARD_NEGATIVE,
131 | ),
132 | Context(
133 | precision=5,
134 | emin=-10,
135 | emax=10,
136 | subnormalize=False,
137 | rounding=ROUND_AWAY_FROM_ZERO,
138 | ),
139 | ]
140 | rounding_contexts = [
141 | RoundTiesToEven,
142 | RoundTowardPositive,
143 | RoundTowardNegative,
144 | RoundTowardZero,
145 | RoundAwayFromZero,
146 | ]
147 |
148 | for original_context in original_contexts:
149 | for rounding_context in rounding_contexts:
150 | with original_context:
151 | with rounding_context:
152 | self.assertEqual(
153 | getcontext().precision, original_context.precision,
154 | )
155 | self.assertEqual(
156 | getcontext().emin, original_context.emin,
157 | )
158 | self.assertEqual(
159 | getcontext().emax, original_context.emax,
160 | )
161 | self.assertEqual(
162 | getcontext().subnormalize,
163 | original_context.subnormalize,
164 | )
165 | self.assertEqual(
166 | getcontext().rounding, rounding_context.rounding,
167 | )
168 |
169 | def test_hashable(self):
170 | # create equal but non-identical contexts
171 | c1 = Context(
172 | emin=-999,
173 | emax=999,
174 | precision=100,
175 | subnormalize=True,
176 | rounding=ROUND_TOWARD_POSITIVE,
177 | )
178 | c2 = Context(
179 | emax=999, emin=-999, rounding=ROUND_TOWARD_POSITIVE
180 | ) + Context(precision=100, subnormalize=True)
181 | self.assertEqual(hash(c1), hash(c2))
182 | self.assertEqual(c1, c2)
183 | self.assertIs(c1 == c2, True)
184 | self.assertIs(c1 != c2, False)
185 |
186 | # distinct contexts
187 | d1 = Context(
188 | emin=-999,
189 | emax=999,
190 | precision=100,
191 | subnormalize=True,
192 | rounding=ROUND_TOWARD_POSITIVE,
193 | )
194 | d2 = Context(
195 | emin=-999,
196 | emax=999,
197 | precision=101,
198 | subnormalize=True,
199 | rounding=ROUND_TOWARD_POSITIVE,
200 | )
201 | self.assertIs(d1 != d2, True)
202 | self.assertIs(d1 == d2, False)
203 |
204 | def test_with(self):
205 | # check use of contexts in with statements
206 | c = Context(
207 | emin=-123,
208 | emax=456,
209 | precision=1729,
210 | subnormalize=True,
211 | rounding=ROUND_TOWARD_POSITIVE,
212 | )
213 | d = Context(
214 | emin=0,
215 | emax=10585,
216 | precision=20,
217 | subnormalize=False,
218 | rounding=ROUND_TOWARD_NEGATIVE,
219 | )
220 |
221 | with c:
222 | # check nested with
223 | with d:
224 | self.assertEqual(getcontext().precision, d.precision)
225 | self.assertEqual(getcontext().emin, d.emin)
226 | self.assertEqual(getcontext().emax, d.emax)
227 | self.assertEqual(getcontext().subnormalize, d.subnormalize)
228 | self.assertEqual(getcontext().rounding, d.rounding)
229 |
230 | # check context is restored on normal exit
231 | self.assertEqual(getcontext().precision, c.precision)
232 | self.assertEqual(getcontext().emin, c.emin)
233 | self.assertEqual(getcontext().emax, c.emax)
234 | self.assertEqual(getcontext().subnormalize, c.subnormalize)
235 | self.assertEqual(getcontext().rounding, c.rounding)
236 |
237 | # check context is restored on abnormal exit, and that exceptions
238 | # raised within the with block are propagated
239 | try:
240 | with d:
241 | raise ValueError
242 | except ValueError:
243 | pass
244 | else:
245 | self.fail("ValueError not propagated from with block")
246 |
247 | self.assertEqual(getcontext().precision, c.precision)
248 | self.assertEqual(getcontext().emin, c.emin)
249 | self.assertEqual(getcontext().emax, c.emax)
250 | self.assertEqual(getcontext().subnormalize, c.subnormalize)
251 | self.assertEqual(getcontext().rounding, c.rounding)
252 |
253 | def test_context_initialised_in_background_thread(self):
254 | # Regression test for mdickinson/bigfloat#78.
255 |
256 | # Timeout for blocking waits, so that a badly written test or
257 | # an unexpected failure mode doesn't cause the whole test suite
258 | # to block.
259 | SAFETY_TIMEOUT = 10.0
260 |
261 | def target(result_queue, precision_changed, continue_event):
262 | # Change the context in a background thread. Put computed
263 | # precisions on a results queue for testing in the main thread.
264 | # We use events to pause execution of the background thread
265 | # so that we can effectively test that the main thread is
266 | # unaffected at that point.
267 | try:
268 | result_queue.put(("PREC", getcontext().precision))
269 | with precision(20):
270 | result_queue.put(("PREC", getcontext().precision))
271 | precision_changed.set()
272 | if not continue_event.wait(timeout=SAFETY_TIMEOUT):
273 | raise RuntimeError("continue_event not received")
274 |
275 | result_queue.put(("PREC", getcontext().precision))
276 | except BaseException as e:
277 | result_queue.put(("EXC", str(e)))
278 | result_queue.put(("DONE",))
279 |
280 | result_queue = queue.Queue()
281 | precision_changed = threading.Event()
282 | continue_event = threading.Event()
283 |
284 | default_precision = DefaultContext.precision
285 |
286 | self.assertEqual(getcontext().precision, default_precision)
287 |
288 | thread = threading.Thread(
289 | target=target,
290 | args=(result_queue, precision_changed, continue_event),
291 | )
292 | thread.start()
293 | try:
294 | precision_changed.wait(timeout=SAFETY_TIMEOUT)
295 | # At this point, the precision in the background thread has
296 | # been changed, but our precision should be unaltered.
297 | self.assertEqual(getcontext().precision, default_precision)
298 | continue_event.set()
299 | finally:
300 | thread.join()
301 |
302 | # Collect messages from the background thread.
303 | messages = []
304 | while True:
305 | message = result_queue.get(timeout=SAFETY_TIMEOUT)
306 | if message[0] == "DONE":
307 | break
308 | messages.append(message)
309 |
310 | self.assertEqual(
311 | messages,
312 | [
313 | ("PREC", DefaultContext.precision),
314 | ("PREC", 20),
315 | ("PREC", DefaultContext.precision),
316 | ],
317 | )
318 |
319 |
320 | if __name__ == "__main__":
321 | unittest.main()
322 |
--------------------------------------------------------------------------------
/bigfloat/context.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | import contextlib
19 | import threading
20 |
21 |
22 | import mpfr
23 |
24 | from bigfloat.rounding_mode import (
25 | RoundingMode,
26 | ROUND_TIES_TO_EVEN,
27 | ROUND_TOWARD_POSITIVE,
28 | ROUND_TOWARD_NEGATIVE,
29 | ROUND_TOWARD_ZERO,
30 | ROUND_AWAY_FROM_ZERO,
31 | )
32 |
33 | EMAX_MAX = mpfr.MPFR_EMAX_DEFAULT
34 | EMIN_MIN = mpfr.MPFR_EMIN_DEFAULT
35 |
36 | PRECISION_MIN = mpfr.MPFR_PREC_MIN
37 | PRECISION_MAX = mpfr.MPFR_PREC_MAX
38 |
39 | EMAX_MIN = max(mpfr.MPFR_EMIN_DEFAULT, mpfr.mpfr_get_emax_min())
40 | EMIN_MAX = min(mpfr.MPFR_EMAX_DEFAULT, mpfr.mpfr_get_emin_max())
41 |
42 |
43 | class Context(object):
44 | """
45 | Information about output format and rounding mode.
46 |
47 | A context provides information about the output format for a
48 | particular operation (target precision, minimum and maximum
49 | exponents, and whether to use gradual underflow), and the
50 | rounding mode used to round the true result to that format.
51 |
52 | Attributes
53 | ----------
54 | 'precision' is the precision in bits (for example, 53 for
55 | standard IEEE double precision).
56 | 'subnormalize' is True for formats that have gradual underflow
57 | and False otherwise.
58 | 'emin' is the minimum exponent; for example, -1073 for IEEE 754
59 | double precision
60 | 'emax' is the maximum exponent; for example, 1024 for IEEE 754
61 | double precision.
62 | 'rounding' is the rounding mode.
63 |
64 | Note that exponent values are relative to a significand scaled to have
65 | absolute value in the range [0.5, 1.0), and that ``emin`` takes
66 | the subnormal range into account when ``subnormalize`` is ``True``.
67 | """
68 |
69 | # Contexts are supposed to be immutable. We make the attributes
70 | # of a Context private, and provide properties to access them in
71 | # order to discourage users from trying to set the attributes
72 | # directly.
73 |
74 | def __new__(
75 | cls,
76 | precision=None,
77 | emin=None,
78 | emax=None,
79 | subnormalize=None,
80 | rounding=None,
81 | ):
82 | if precision is not None and not (
83 | PRECISION_MIN <= precision <= PRECISION_MAX
84 | ):
85 | raise ValueError(
86 | "Precision p should satisfy %d <= p <= %d."
87 | % (PRECISION_MIN, PRECISION_MAX)
88 | )
89 | if emin is not None and not EMIN_MIN <= emin <= EMIN_MAX:
90 | raise ValueError(
91 | "exponent bound emin should satisfy "
92 | "%d <= emin <= %d" % (EMIN_MIN, EMIN_MAX)
93 | )
94 | if emax is not None and not EMAX_MIN <= emax <= EMAX_MAX:
95 | raise ValueError(
96 | "exponent bound emax should satisfy "
97 | "%d <= emax <= %d" % (EMAX_MIN, EMAX_MAX)
98 | )
99 | if rounding is not None:
100 | rounding = RoundingMode(rounding)
101 | if subnormalize is not None and subnormalize not in [False, True]:
102 | raise ValueError("subnormalize should be either False or True")
103 | self = object.__new__(cls)
104 | self._precision = precision
105 | self._emin = emin
106 | self._emax = emax
107 | self._subnormalize = subnormalize
108 | self._rounding = rounding
109 | return self
110 |
111 | def __add__(self, other):
112 | """For contexts self and other, self + other is a new Context
113 | combining self and other: for attributes that are defined in
114 | both self and other, the attribute from other takes
115 | precedence."""
116 |
117 | return Context(
118 | precision=(
119 | other.precision
120 | if other.precision is not None
121 | else self.precision
122 | ),
123 | emin=other.emin if other.emin is not None else self.emin,
124 | emax=other.emax if other.emax is not None else self.emax,
125 | subnormalize=(
126 | other.subnormalize
127 | if other.subnormalize is not None
128 | else self.subnormalize
129 | ),
130 | rounding=(
131 | other.rounding if other.rounding is not None else self.rounding
132 | ),
133 | )
134 |
135 | def __eq__(self, other):
136 | return (
137 | self.precision == other.precision
138 | and self.emin == other.emin
139 | and self.emax == other.emax
140 | and self.subnormalize == other.subnormalize
141 | and self.rounding == other.rounding
142 | )
143 |
144 | def __ne__(self, other):
145 | return not (self == other)
146 |
147 | def __hash__(self):
148 | return hash(
149 | (
150 | self.precision,
151 | self.emin,
152 | self.emax,
153 | self.subnormalize,
154 | self.rounding,
155 | )
156 | )
157 |
158 | @property
159 | def precision(self):
160 | return self._precision
161 |
162 | @property
163 | def rounding(self):
164 | return self._rounding
165 |
166 | @property
167 | def emin(self):
168 | return self._emin
169 |
170 | @property
171 | def emax(self):
172 | return self._emax
173 |
174 | @property
175 | def subnormalize(self):
176 | return self._subnormalize
177 |
178 | def __repr__(self):
179 | args = []
180 | if self.precision is not None:
181 | args.append("precision=%r" % self.precision)
182 | if self.emax is not None:
183 | args.append("emax=%r" % self.emax)
184 | if self.emin is not None:
185 | args.append("emin=%r" % self.emin)
186 | if self.subnormalize is not None:
187 | args.append("subnormalize=%r" % self.subnormalize)
188 | if self.rounding is not None:
189 | args.append("rounding=%r" % self.rounding)
190 | return "Context(%s)" % ", ".join(args)
191 |
192 | __str__ = __repr__
193 |
194 | def __enter__(self):
195 | _pushcontext(self)
196 |
197 | def __exit__(self, *args):
198 | _popcontext()
199 |
200 |
201 | # some useful contexts
202 |
203 | # DefaultContext is the context that the module always starts with.
204 | DefaultContext = Context(
205 | rounding=ROUND_TIES_TO_EVEN,
206 | precision=113,
207 | emax=16384,
208 | emin=-16493,
209 | subnormalize=True,
210 | )
211 |
212 | # EmptyContext is useful for situations where a context is
213 | # required, but no change to the current context is desirable
214 | EmptyContext = Context()
215 |
216 | # WideExponentContext has the largest exponent range allowed
217 | # by MPFR; precision and rounding mode are not specified.
218 | WideExponentContext = Context(
219 | emax=EMAX_MAX, emin=EMIN_MIN, subnormalize=False,
220 | )
221 |
222 |
223 | # thread-local variables:
224 | # __bigfloat_context__: current context
225 | # __context_stack__: context stack, used by with statement
226 |
227 | local = threading.local()
228 |
229 |
230 | def getcontext(_local=local):
231 | """
232 | Return the current context.
233 |
234 | Also initialises the context the first time it's called in each thread.
235 |
236 | """
237 | try:
238 | return _local.__bigfloat_context__
239 | except AttributeError:
240 | context = _local.__bigfloat_context__ = DefaultContext
241 | return context
242 |
243 |
244 | def setcontext(context, _local=local):
245 | """
246 | Set the current context to that given.
247 |
248 | Attributes provided by ``context`` override those in the current
249 | context. If ``context`` doesn't specify a particular attribute,
250 | the attribute from the current context shows through.
251 |
252 | """
253 | oldcontext = getcontext()
254 | _local.__bigfloat_context__ = oldcontext + context
255 |
256 |
257 | def _pushcontext(context, _local=local):
258 | try:
259 | context_stack = _local.__context_stack__
260 | except AttributeError:
261 | context_stack = _local.__context_stack__ = []
262 | context_stack.append(getcontext())
263 | setcontext(context)
264 |
265 |
266 | def _popcontext(_local=local):
267 | # It's safe to assume that __context_stack__ is already initialised and
268 | # non-empty here, since any _popcontext call will have been preceded by a
269 | # corresponding _pushcontext call.
270 | setcontext(_local.__context_stack__.pop())
271 |
272 |
273 | # Don't contaminate the namespace.
274 | del threading, local
275 |
276 |
277 | def precision(prec):
278 | """
279 | Return context specifying the given precision.
280 |
281 | ``precision(prec)`` is exactly equivalent to ``Context(precision=prec)``.
282 |
283 | """
284 | return Context(precision=prec)
285 |
286 |
287 | def rounding(rnd):
288 | """
289 | Return a context giving the specified rounding mode.
290 |
291 | ``rounding(rnd)`` is exactly equivalent to ``Context(rounding=rnd)``.
292 |
293 | """
294 | return Context(rounding=rnd)
295 |
296 |
297 | def extra_precision(prec):
298 | """
299 | Return copy of the current context with the precision increased by
300 | ``prec``. Equivalent to ``Context(precision=getcontext().precision + p)``.
301 |
302 | >>> getcontext().precision
303 | 53
304 | >>> extra_precision(10).precision
305 | 63
306 | >>> with extra_precision(20):
307 | ... gamma(1.5)
308 | ...
309 | BigFloat.exact('0.88622692545275801364912', precision=73)
310 |
311 | """
312 | c = getcontext()
313 | return Context(precision=c.precision + prec)
314 |
315 |
316 | @contextlib.contextmanager
317 | def _temporary_exponent_bounds(emin, emax):
318 | old_emin = mpfr.mpfr_get_emin()
319 | mpfr.mpfr_set_emin(emin)
320 | try:
321 | old_emax = mpfr.mpfr_get_emax()
322 | mpfr.mpfr_set_emax(emax)
323 | try:
324 | yield
325 | finally:
326 | mpfr.mpfr_set_emax(old_emax)
327 | finally:
328 | mpfr.mpfr_set_emin(old_emin)
329 |
330 |
331 | def _apply_function_in_context(cls, f, args, context):
332 | """ Apply an MPFR function 'f' to the given arguments 'args', rounding to
333 | the given context. Returns a new Mpfr object with precision taken from
334 | the current context.
335 |
336 | """
337 | rounding = context.rounding
338 | bf = mpfr.Mpfr_t.__new__(cls)
339 | mpfr.mpfr_init2(bf, context.precision)
340 | args = (bf,) + args + (rounding,)
341 | ternary = f(*args)
342 | with _temporary_exponent_bounds(context.emin, context.emax):
343 | ternary = mpfr.mpfr_check_range(bf, ternary, rounding)
344 | if context.subnormalize:
345 | # mpfr_subnormalize doesn't set underflow and
346 | # subnormal flags, so we do that ourselves. We choose
347 | # to set the underflow flag for *all* cases where the
348 | # 'after rounding' result is smaller than the smallest
349 | # normal number, even if that result is exact.
350 |
351 | # if bf is zero but ternary is nonzero, the underflow
352 | # flag will already have been set by mpfr_check_range;
353 | underflow = (
354 | mpfr.mpfr_number_p(bf)
355 | and not mpfr.mpfr_zero_p(bf)
356 | and (
357 | mpfr.mpfr_get_exp(bf)
358 | < context.precision - 1 + context.emin
359 | )
360 | )
361 | if underflow:
362 | mpfr.mpfr_set_underflow()
363 | ternary = mpfr.mpfr_subnormalize(bf, ternary, rounding)
364 | if ternary:
365 | mpfr.mpfr_set_inexflag()
366 | return bf
367 |
368 |
369 | def _apply_function_in_current_context(cls, f, args, context):
370 | with (context if context is not None else EmptyContext):
371 | return _apply_function_in_context(cls, f, args, getcontext())
372 |
373 |
374 | # provided rounding modes are implemented as contexts, so that
375 | # they can be used directly in with statements
376 | RoundTiesToEven = rounding(ROUND_TIES_TO_EVEN)
377 | RoundTowardPositive = rounding(ROUND_TOWARD_POSITIVE)
378 | RoundTowardNegative = rounding(ROUND_TOWARD_NEGATIVE)
379 | RoundTowardZero = rounding(ROUND_TOWARD_ZERO)
380 | RoundAwayFromZero = rounding(ROUND_AWAY_FROM_ZERO)
381 |
--------------------------------------------------------------------------------
/bigfloat/test/test_formatting.py:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | import unittest
19 |
20 | from bigfloat import (
21 | BigFloat,
22 | double_precision,
23 | RoundTiesToEven,
24 | getcontext,
25 | setcontext,
26 | )
27 |
28 |
29 | DefaultTestContext = double_precision + RoundTiesToEven
30 |
31 |
32 | class TestFormatting(unittest.TestCase):
33 | def setUp(self):
34 | self._original_context = getcontext()
35 | setcontext(DefaultTestContext)
36 |
37 | def tearDown(self):
38 | setcontext(self._original_context)
39 | del self._original_context
40 |
41 | def test_format(self):
42 | # Fixed precision formatting.
43 | test_triples = [
44 | (BigFloat(2), ".6f", "2.000000"),
45 | # 'F' behaves the same as 'f' except for infinities and nans.
46 | (BigFloat(2), ".6F", "2.000000"),
47 | # Extra zeros in the precision should be fine.
48 | (BigFloat(2), ".06f", "2.000000"),
49 | (BigFloat(2), ".5f", "2.00000"),
50 | # . only retained with 'alternate' formatting
51 | (BigFloat(2), ".0f", "2"),
52 | # Default precision is 6.
53 | (BigFloat(2), "f", "2.000000"),
54 | (BigFloat("nan"), "f", "nan"),
55 | (BigFloat("-nan"), "f", "nan"),
56 | (BigFloat("inf"), "f", "inf"),
57 | (BigFloat("-inf"), "f", "-inf"),
58 | (BigFloat("nan"), "F", "NAN"),
59 | (BigFloat("-nan"), "F", "NAN"),
60 | (BigFloat("inf"), "F", "INF"),
61 | (BigFloat("-inf"), "F", "-INF"),
62 | # Rounding behaviour.
63 | (BigFloat("3.1415926535"), ".6f", "3.141593"),
64 | (BigFloat("3.1415926535"), ".5f", "3.14159"),
65 | (BigFloat("3.1415926535"), ".4f", "3.1416"),
66 | (BigFloat("3.1415926535"), ".3f", "3.142"),
67 | (BigFloat("3.1415926535"), ".2f", "3.14"),
68 | (BigFloat("3.1415926535"), ".1f", "3.1"),
69 | (BigFloat("3.1415926535"), ".0f", "3"),
70 | # Sign specification.
71 | (BigFloat(+2), "+.3f", "+2.000"),
72 | (BigFloat(-2), "+.3f", "-2.000"),
73 | (BigFloat(+2), " .3f", " 2.000"),
74 | (BigFloat(-2), " .3f", "-2.000"),
75 | (BigFloat(+2), "-.3f", "2.000"),
76 | (BigFloat(-2), "-.3f", "-2.000"),
77 | (BigFloat(+2), ".3f", "2.000"),
78 | (BigFloat(-2), ".3f", "-2.000"),
79 | # With infinities and nans; note that MPFR doesn't include
80 | # these signs.
81 | (BigFloat("+inf"), "+.3f", "+inf"),
82 | (BigFloat("-inf"), "+.3f", "-inf"),
83 | (BigFloat("+nan"), "+.3f", "+nan"),
84 | (BigFloat("+inf"), "-.3f", "inf"),
85 | (BigFloat("-inf"), "-.3f", "-inf"),
86 | (BigFloat("+nan"), "-.3f", "nan"),
87 | (BigFloat("+inf"), " .3f", " inf"),
88 | (BigFloat("-inf"), " .3f", "-inf"),
89 | (BigFloat("+nan"), " .3f", " nan"),
90 | # Alternate formatting.
91 | (BigFloat(2), "#.0f", "2."),
92 | (BigFloat(2), "+#.0f", "+2."),
93 | # Minimum field width.
94 | (BigFloat(2), "10.3f", " 2.000"),
95 | (BigFloat(2), "6.3f", " 2.000"),
96 | (BigFloat(2), "5.3f", "2.000"),
97 | (BigFloat(2), "4.3f", "2.000"),
98 | (BigFloat(2), "1.3f", "2.000"),
99 | # Minimum field width in combination with sign.
100 | (BigFloat(2), "+10.3f", " +2.000"),
101 | (BigFloat(-23), "+10.3f", " -23.000"),
102 | # Zero padding.
103 | (BigFloat(2), "010.3f", "000002.000"),
104 | (BigFloat(2), "+010.3f", "+00002.000"),
105 | (BigFloat(2), " 010.3f", " 00002.000"),
106 | (BigFloat(2), "0010.3f", "000002.000"),
107 | # Alignment and filling.
108 | (BigFloat(2), "<10.3f", "2.000 "),
109 | (BigFloat(2), ">10.3f", " 2.000"),
110 | (BigFloat(2), "^10.3f", " 2.000 "),
111 | (BigFloat(2), "<10.2f", "2.00 "),
112 | (BigFloat(2), ">10.2f", " 2.00"),
113 | (BigFloat(2), "^10.2f", " 2.00 "),
114 | (BigFloat(2), "<4.2f", "2.00"),
115 | (BigFloat(2), ">4.2f", "2.00"),
116 | (BigFloat(2), "^4.2f", "2.00"),
117 | (BigFloat(2), "<3.2f", "2.00"),
118 | (BigFloat(2), ">3.2f", "2.00"),
119 | (BigFloat(2), "^3.2f", "2.00"),
120 | (BigFloat(2), "X<10.3f", "2.000XXXXX"),
121 | (BigFloat(2), "X>10.3f", "XXXXX2.000"),
122 | (BigFloat(2), "X^10.3f", "XX2.000XXX"),
123 | (BigFloat(2), "X<10.2f", "2.00XXXXXX"),
124 | (BigFloat(2), "X>10.2f", "XXXXXX2.00"),
125 | (BigFloat(2), "X^10.2f", "XXX2.00XXX"),
126 | (BigFloat(2), "X<4.2f", "2.00"),
127 | (BigFloat(2), "X>4.2f", "2.00"),
128 | (BigFloat(2), "X^4.2f", "2.00"),
129 | (BigFloat(2), "X<3.2f", "2.00"),
130 | (BigFloat(2), "X>3.2f", "2.00"),
131 | (BigFloat(2), "X^3.2f", "2.00"),
132 | (BigFloat(2), "X=+10.3f", "+XXXX2.000"),
133 | (BigFloat(2), " =+10.3f", "+ 2.000"),
134 | (BigFloat(2), "0=+10.3f", "+00002.000"),
135 | (BigFloat(2), "\x00=+10.3f", "+\x00\x00\x00\x002.000"),
136 | (BigFloat(2), "\n=+10.3f", "+\n\n\n\n2.000"),
137 | # e-style formatting
138 | (BigFloat(2), ".6e", "2.000000e+00"),
139 | (BigFloat(3.141592653589793), ".6e", "3.141593e+00"),
140 | (BigFloat(3.141592653589793), ".6E", "3.141593E+00"),
141 | (BigFloat(314.1592653589793), ".6e", "3.141593e+02"),
142 | (BigFloat(314.1592653589793), ".6E", "3.141593E+02"),
143 | (BigFloat("nan"), "e", "nan"),
144 | (BigFloat("-nan"), "e", "nan"),
145 | (BigFloat("inf"), "e", "inf"),
146 | (BigFloat("-inf"), "e", "-inf"),
147 | (BigFloat("nan"), "E", "NAN"),
148 | (BigFloat("-nan"), "E", "NAN"),
149 | (BigFloat("inf"), "E", "INF"),
150 | (BigFloat("-inf"), "E", "-INF"),
151 | (BigFloat(314.1592653589793), ".0e", "3e+02"),
152 | (BigFloat(314.1592653589793), "#.0e", "3.e+02"),
153 | (BigFloat(314.1592653589793), "e", "3.1415926535897933e+02"),
154 | (BigFloat(314.1592653589793), "6e", "3.1415926535897933e+02"),
155 | # g-style formatting
156 | (BigFloat(3.141592653589793), ".7g", "3.141593"),
157 | (BigFloat(3.141592653589793), ".7G", "3.141593"),
158 | (BigFloat(314.1592653589793), ".7g", "314.1593"),
159 | (BigFloat(31415.92653589793), ".7g", "31415.93"),
160 | (BigFloat(3141592.653589793), ".7g", "3141593"),
161 | (BigFloat(3141592.653589793), ".7G", "3141593"),
162 | (BigFloat(31415926.53589793), ".7g", "3.141593e+07"),
163 | (BigFloat(31415926.53589793), ".7G", "3.141593E+07"),
164 | (BigFloat("nan"), "g", "nan"),
165 | (BigFloat("-nan"), "g", "nan"),
166 | (BigFloat("inf"), "g", "inf"),
167 | (BigFloat("-inf"), "g", "-inf"),
168 | (BigFloat("nan"), "G", "NAN"),
169 | (BigFloat("-nan"), "G", "NAN"),
170 | (BigFloat("inf"), "G", "INF"),
171 | (BigFloat("-inf"), "G", "-INF"),
172 | (BigFloat(314.1592653589793), ".0g", "3e+02"),
173 | (BigFloat(314.1592653589793), ".1g", "3e+02"),
174 | (BigFloat(314.1592653589793), "#.0g", "3.e+02"),
175 | (BigFloat(314.1592653589793), "#.1g", "3.e+02"),
176 | (BigFloat(314.1592653589793), "g", "314.159"),
177 | (BigFloat(314.1592653589793), "6g", "314.159"),
178 | # Trailing zeros are stripped, except in alternate style.
179 | (BigFloat(2), ".6g", "2"),
180 | (BigFloat(0.000023), ".6g", "2.3e-05"),
181 | (BigFloat(0.00023), ".6g", "0.00023"),
182 | (BigFloat(2.3), ".6g", "2.3"),
183 | (BigFloat(230), ".6g", "230"),
184 | (BigFloat(230000), ".6g", "230000"),
185 | (BigFloat(2300000), ".6g", "2.3e+06"),
186 | (BigFloat(2), "#.6g", "2.00000"),
187 | # %-formatting
188 | (BigFloat(3.141592653589793), ".2%", "314.16%"),
189 | (BigFloat(3.141592653589793), ".1%", "314.2%"),
190 | (BigFloat(3.141592653589793), ".0%", "314%"),
191 | (BigFloat(3.141592653589793), "%", "314.159265%"),
192 | (BigFloat(0.0234), ".3%", "2.340%"),
193 | (BigFloat(0.00234), ".3%", "0.234%"),
194 | (BigFloat(0.000234), ".3%", "0.023%"),
195 | (BigFloat(0.000234), ".3U%", "0.024%"),
196 | (BigFloat(0.0000234), ".3%", "0.002%"),
197 | (BigFloat(0.00000234), ".3%", "0.000%"),
198 | (BigFloat(0.00000234), ".3Y%", "0.001%"),
199 | (BigFloat(-3.141592653589793), ".2%", "-314.16%"),
200 | (BigFloat(-3.141592653589793), ".1%", "-314.2%"),
201 | (BigFloat(-3.141592653589793), ".0%", "-314%"),
202 | (BigFloat(-3.141592653589793), "%", "-314.159265%"),
203 | (BigFloat(-0.0234), ".3%", "-2.340%"),
204 | (BigFloat(-0.00234), ".3%", "-0.234%"),
205 | (BigFloat(-0.000234), ".3%", "-0.023%"),
206 | (BigFloat(-0.000234), ".3U%", "-0.023%"),
207 | (BigFloat(-0.0000234), ".3%", "-0.002%"),
208 | (BigFloat(-0.00000234), ".3%", "-0.000%"),
209 | (BigFloat(-0.00000234), ".3Y%", "-0.001%"),
210 | (BigFloat("0"), ".3%", "0.000%"),
211 | (BigFloat("-0"), ".3%", "-0.000%"),
212 | # We should see the '%' even on infinities and nans.
213 | (BigFloat("inf"), ".3%", "inf%"),
214 | (BigFloat("-inf"), ".3%", "-inf%"),
215 | (BigFloat("nan"), ".3%", "nan%"),
216 | (BigFloat("inf"), "+.3%", "+inf%"),
217 | (BigFloat("-inf"), "+.3%", "-inf%"),
218 | (BigFloat("nan"), "+.3%", "+nan%"),
219 | # Hexadecimal formatting. It's not 100% clear how MPFR
220 | # chooses the exponent here.
221 | (BigFloat(1.5), ".6a", "0x1.800000p+0"),
222 | (BigFloat(1.5), ".5a", "0x1.80000p+0"),
223 | (BigFloat(1.5), ".1a", "0x1.8p+0"),
224 | (BigFloat(1.5), ".0a", "0xcp-3"),
225 | (BigFloat(1.5), ".6A", "0X1.800000P+0"),
226 | (BigFloat(3.0), ".6a", "0x3.000000p+0"),
227 | (BigFloat(3.141592653589793), ".6a", "0x3.243f6bp+0"),
228 | (BigFloat(3.141592653589793), ".5a", "0x3.243f7p+0"),
229 | (BigFloat(3.141592653589793), ".4a", "0x3.243fp+0"),
230 | (BigFloat(3.141592653589793), ".3a", "0x3.244p+0"),
231 | (BigFloat(3.141592653589793), ".2a", "0x3.24p+0"),
232 | (BigFloat(3.141592653589793), ".1a", "0x3.2p+0"),
233 | (BigFloat(3.141592653589793), ".0a", "0xdp-2"),
234 | # With no precision, outputs enough digits to give an
235 | # exact representation.
236 | (BigFloat(3.141592653589793), "a", "0x3.243f6a8885a3p+0"),
237 | (BigFloat(10.0), ".6a", "0xa.000000p+0"),
238 | (BigFloat(16.0), ".6a", "0x1.000000p+4"),
239 | (BigFloat("nan"), "a", "nan"),
240 | (BigFloat("-nan"), "a", "nan"),
241 | (BigFloat("inf"), "a", "inf"),
242 | (BigFloat("-inf"), "a", "-inf"),
243 | (BigFloat("nan"), "A", "NAN"),
244 | (BigFloat("-nan"), "A", "NAN"),
245 | (BigFloat("inf"), "A", "INF"),
246 | (BigFloat("-inf"), "A", "-INF"),
247 | # Binary formatting.
248 | (BigFloat("2.25"), "b", "1.001p+1"),
249 | (BigFloat("-2.25"), "b", "-1.001p+1"),
250 | (BigFloat("nan"), "b", "nan"),
251 | (BigFloat("inf"), "b", "inf"),
252 | (BigFloat("-inf"), "b", "-inf"),
253 | # Rounding mode.
254 | # Round up.
255 | (BigFloat("-56.127"), ".2Uf", "-56.12"),
256 | (BigFloat("-56.125"), ".2Uf", "-56.12"),
257 | (BigFloat("-56.123"), ".2Uf", "-56.12"),
258 | (BigFloat("56.123"), ".2Uf", "56.13"),
259 | (BigFloat("56.125"), ".2Uf", "56.13"),
260 | (BigFloat("56.127"), ".2Uf", "56.13"),
261 | # Round down.
262 | (BigFloat("-56.127"), ".2Df", "-56.13"),
263 | (BigFloat("-56.125"), ".2Df", "-56.13"),
264 | (BigFloat("-56.123"), ".2Df", "-56.13"),
265 | (BigFloat("56.123"), ".2Df", "56.12"),
266 | (BigFloat("56.125"), ".2Df", "56.12"),
267 | (BigFloat("56.127"), ".2Df", "56.12"),
268 | # Round away from zero.
269 | (BigFloat("-56.127"), ".2Yf", "-56.13"),
270 | (BigFloat("-56.125"), ".2Yf", "-56.13"),
271 | (BigFloat("-56.123"), ".2Yf", "-56.13"),
272 | (BigFloat("56.123"), ".2Yf", "56.13"),
273 | (BigFloat("56.125"), ".2Yf", "56.13"),
274 | (BigFloat("56.127"), ".2Yf", "56.13"),
275 | # Round toward zero.
276 | (BigFloat("-56.127"), ".2Zf", "-56.12"),
277 | (BigFloat("-56.125"), ".2Zf", "-56.12"),
278 | (BigFloat("-56.123"), ".2Zf", "-56.12"),
279 | (BigFloat("56.123"), ".2Zf", "56.12"),
280 | (BigFloat("56.125"), ".2Zf", "56.12"),
281 | (BigFloat("56.127"), ".2Zf", "56.12"),
282 | # Round to nearest (ties to even).
283 | (BigFloat("-56.127"), ".2Nf", "-56.13"),
284 | (BigFloat("-56.125"), ".2Nf", "-56.12"),
285 | (BigFloat("-56.123"), ".2Nf", "-56.12"),
286 | (BigFloat("56.123"), ".2Nf", "56.12"),
287 | (BigFloat("56.125"), ".2Nf", "56.12"),
288 | (BigFloat("56.127"), ".2Nf", "56.13"),
289 | # Missing rounding mode implies round to nearest.
290 | (BigFloat("-56.127"), ".2f", "-56.13"),
291 | (BigFloat("-56.125"), ".2f", "-56.12"),
292 | (BigFloat("-56.123"), ".2f", "-56.12"),
293 | (BigFloat("56.123"), ".2f", "56.12"),
294 | (BigFloat("56.125"), ".2f", "56.12"),
295 | (BigFloat("56.127"), ".2f", "56.13"),
296 | # Missing type behaves like str formatting.
297 | (BigFloat("123"), ".0", "1e+02"),
298 | (BigFloat("123"), ".1", "1e+02"),
299 | (BigFloat("123"), ".2", "1.2e+02"),
300 | (BigFloat("123"), ".2U", "1.3e+02"),
301 | (BigFloat("123"), ".2D", "1.2e+02"),
302 | (BigFloat("123"), ".3", "123"),
303 | # 'alternate' flag is currently ignored.
304 | (BigFloat("123"), "#.3", "123"),
305 | (BigFloat("123"), ".4", "123.0"),
306 | (BigFloat("123"), "#.4", "123.0"),
307 | (BigFloat("123"), ".0", "1e+02"),
308 | (BigFloat("123"), "", "123.00000000000000"),
309 | (BigFloat("nan"), "", "nan"),
310 | (BigFloat("inf"), "", "inf"),
311 | (BigFloat("-inf"), "", "-inf"),
312 | ]
313 | for bf, fmt, expected_output in test_triples:
314 | result = format(bf, fmt)
315 | self.assertEqual(
316 | result, expected_output, msg=(bf, fmt, expected_output)
317 | )
318 |
319 | def test_empty_format_matches_str(self):
320 | test_values = [
321 | BigFloat("0.0"),
322 | BigFloat("-0.0"),
323 | BigFloat("1.0"),
324 | BigFloat("-2.3"),
325 | BigFloat("1e100"),
326 | BigFloat("1e-100"),
327 | BigFloat("nan"),
328 | BigFloat("inf"),
329 | BigFloat("-inf"),
330 | ]
331 | for value in test_values:
332 | self.assertEqual(str(value), format(value, ""))
333 |
334 | def test_invalid_formats(self):
335 | invalid_formats = [
336 | # Can't specify fill/align *and* zero padding at once ...
337 | "X<010.2f",
338 | ">010.2f",
339 | " ^010.2f",
340 | "=010.2f",
341 | # ... even if the fill/align matches the zero padding!
342 | "0=010.2f",
343 | # a . must be followed by a precision.
344 | ".f",
345 | "10.g",
346 | ]
347 | for fmt in invalid_formats:
348 | with self.assertRaises(ValueError):
349 | format(BigFloat(2), fmt)
350 |
--------------------------------------------------------------------------------
/docs/source/tutorial/index.rst:
--------------------------------------------------------------------------------
1 | Tutorial
2 | --------
3 |
4 | .. currentmodule:: bigfloat
5 |
6 | Start by importing the contents of the package with:
7 |
8 | >>> from bigfloat import *
9 |
10 | You should be a little bit careful here: this import brings a fairly large
11 | number of functions into the current namespace, some of which shadow existing
12 | Python builtins, namely :func:`abs`, :func:`max`, :func:`min`, :func:`pow`,
13 | :func:`round`, :func:`sum`, and (on Python 2 only) :func:`cmp`. In normal
14 | usage you'll probably only want to import the classes and functions that you
15 | actually need.
16 |
17 |
18 | :class:`BigFloat` construction
19 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20 |
21 | The main type of interest is the :class:`BigFloat` class. The
22 | :class:`BigFloat` type is an immutable binary floating-point type. A
23 | :class:`BigFloat` instance can be created from an integer, a float or
24 | a string:
25 |
26 | >>> BigFloat(123)
27 | BigFloat.exact('123.000000000000000000000000000000000', precision=113)
28 | >>> BigFloat("-4.56")
29 | BigFloat.exact('-4.55999999999999999999999999999999966', precision=113)
30 |
31 | Each :class:`BigFloat` instance has both a *value* and a *precision*.
32 | The precision gives the number of bits used to store the significand
33 | of the :class:`BigFloat`. The *value* of a finite nonzero
34 | :class:`BigFloat` with precision ``p`` is a real number of the form
35 | ``(-1)**s * m * 2**e``, where the *sign* ``s`` is either ``0`` or
36 | ``1``, the *significand* ``m`` is a number in the half-open interval
37 | [0.5, 1.0) that can be expressed in the form ``n/2**p`` for some
38 | integer ``n``, and ``e`` is an integer giving the *exponent*. In
39 | addition, zeros (positive and negative), infinities and NaNs are
40 | representable. Just like Python floats, the printed form of a
41 | :class:`BigFloat` shows only a decimal approximation to the exact
42 | stored value, for the benefit of human readers.
43 |
44 | The precision of a newly-constructed :class:`BigFloat` instance is
45 | dictated by the *current precision*, which defaults to ``113`` (the precision
46 | of the IEEE 754 "binary128" format, a.k.a. quadruple precision). This
47 | setting can be overridden by supplying the ``context`` keyword
48 | argument to the constructor:
49 |
50 | >>> BigFloat(-4.56, context=precision(24))
51 | BigFloat.exact('-4.55999994', precision=24)
52 |
53 | The first argument to the :class:`BigFloat` constructor is rounded to
54 | the correct precision using the *current rounding mode*, which
55 | defaults to :data:`RoundTiesToEven`; again, this can be overridden with
56 | the ``context`` keyword argument:
57 |
58 | >>> BigFloat('3.14')
59 | BigFloat.exact('3.14000000000000000000000000000000011', precision=113)
60 | >>> BigFloat('3.14', context=RoundTowardZero)
61 | BigFloat.exact('3.13999999999999999999999999999999972', precision=113)
62 | >>> BigFloat('3.14', context=RoundTowardPositive + precision(24))
63 | BigFloat.exact('3.14000010', precision=24)
64 |
65 | More generally, the second argument to the :class:`BigFloat` constructor can be
66 | any instance of the :class:`Context` class. The various rounding modes are all
67 | :class:`Context` instances, and :func:`precision` is a function returning a
68 | :class:`Context`:
69 |
70 | >>> RoundTowardNegative
71 | Context(rounding=ROUND_TOWARD_NEGATIVE)
72 | >>> precision(1000)
73 | Context(precision=1000)
74 |
75 | :class:`Context` instances can be combined by addition, as seen above.
76 |
77 | >>> precision(1000) + RoundTowardNegative
78 | Context(precision=1000, rounding=ROUND_TOWARD_NEGATIVE)
79 |
80 | When adding two contexts that both specify values for a particular
81 | attribute, the value for the right-hand addend takes precedence::
82 |
83 | >>> c = Context(subnormalize=False, rounding=ROUND_TOWARD_POSITIVE)
84 | >>> double_precision
85 | Context(precision=53, emax=1024, emin=-1073, subnormalize=True)
86 | >>> double_precision + c
87 | Context(precision=53, emax=1024, emin=-1073, subnormalize=False,
88 | rounding=ROUND_TOWARD_POSITIVE)
89 | >>> c + double_precision
90 | Context(precision=53, emax=1024, emin=-1073, subnormalize=True,
91 | rounding=ROUND_TOWARD_POSITIVE)
92 |
93 | The :mod:`bigfloat` package also defines various constant :class:`Context`
94 | instances. For example, :data:`quadruple_precision` is a :class:`Context`
95 | object that corresponds to the IEEE 754 binary128 interchange format::
96 |
97 | >>> quadruple_precision
98 | Context(precision=113, emax=16384, emin=-16493, subnormalize=True)
99 | >>> BigFloat('1.1', quadruple_precision)
100 | BigFloat.exact('1.10000000000000000000000000000000008', precision=113)
101 |
102 | The current settings for precision and rounding mode are given by the
103 | :ref:`current context `, accessible via the :func:`getcontext`
104 | function:
105 |
106 | >>> getcontext()
107 | Context(precision=113, emax=16384, emin=-16493, subnormalize=True,
108 | rounding=ROUND_TIES_TO_EVEN)
109 |
110 | There's also a :func:`setcontext` function for changing the current
111 | context; however, the preferred method for making temporary changes to
112 | the current context is to use Python's with statement. More on this below.
113 |
114 | Note that (in contrast to Python's standard library :mod:`decimal` module),
115 | :class:`Context` instances are immutable.
116 |
117 | There's a second method for constructing :class:`BigFloat`
118 | instances: :meth:`BigFloat.exact`. Just like the usual constructor,
119 | :meth:`BigFloat.exact` accepts integers, floats and strings. However,
120 | for integers and floats it performs an exact conversion, creating a
121 | :class:`BigFloat` instance with precision large enough to hold the
122 | integer or float exactly (regardless of the current precision
123 | setting):
124 |
125 | >>> BigFloat.exact(-123)
126 | BigFloat.exact('-123.0', precision=7)
127 | >>> BigFloat.exact(7**30)
128 | BigFloat.exact('22539340290692258087863249.0', precision=85)
129 | >>> BigFloat.exact(-56.7)
130 | BigFloat.exact('-56.700000000000003', precision=53)
131 |
132 | For strings, :meth:`BigFloat.exact` accepts a second ``precision`` argument,
133 | and always rounds using the :data:`ROUND_TIES_TO_EVEN` rounding mode.
134 |
135 | >>> BigFloat.exact('1.1', precision=80)
136 | BigFloat.exact('1.1000000000000000000000003', precision=80)
137 |
138 | The result of a call to :meth:`BigFloat.exact` is independent of the current
139 | context; this is why the :func:`repr` of a :class:`BigFloat` is expressed in
140 | terms of :meth:`BigFloat.exact`. The :class:`str` of a :class:`BigFloat` looks
141 | prettier, but doesn't supply enough information to recover that
142 | :class:`BigFloat` exactly if you don't know the precision:
143 |
144 | >>> print(BigFloat('1e1000', precision(20)))
145 | 9.9999988e+999
146 | >>> print(BigFloat('1e1000', precision(21)))
147 | 9.9999988e+999
148 |
149 | Arithmetic on :class:`BigFloat` instances
150 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
151 |
152 | All the usual arithmetic operations apply to :class:`BigFloat` instances, and
153 | those instances can be freely mixed with integers and floats (but not strings!)
154 | in those operations:
155 |
156 | >>> BigFloat(1234)/3
157 | BigFloat.exact('411.333333333333333333333333333333317', precision=113)
158 | >>> BigFloat('1e1233')**0.5
159 | BigFloat.exact('3.16227766016837933199889354443271851e+616', precision=113)
160 |
161 | As with the :class:`BigFloat` constructor, the precision for the result is
162 | taken from the current context, as is the rounding mode used to round
163 | the exact mathematical result to the nearest :class:`BigFloat`.
164 |
165 | For mixed-type operations, the integer or float is converted *exactly*
166 | to a :class:`BigFloat` before the operation (as though the
167 | :meth:`BigFloat.exact` constructor had been applied to it). So
168 | there's only a single point where precision might be lost: namely,
169 | when the result of the operation is rounded to the nearest value
170 | representable as a :class:`BigFloat`.
171 |
172 | .. note::
173 |
174 | The current precision and rounding mode even apply to the unary
175 | plus and minus operations. In particular, ``+x`` is not
176 | necessarily a no-op for a :class:`BigFloat` instance x:
177 |
178 | >>> BigFloat.exact(7**100)
179 | BigFloat.exact('323447650962475799134464776910021681085720319890462540093389
180 | 5331391691459636928060001.0', precision=281)
181 | >>> +BigFloat.exact(7**100)
182 | BigFloat.exact('3.23447650962475799134464776910021692e+84', precision=113)
183 |
184 | This makes the unary plus operator useful as a way to round a
185 | result produced in a different context to the current context.
186 |
187 | For each arithmetic operation the :mod:`bigfloat` package exports a
188 | corresponding function. For example, the :func:`div` function
189 | corresponds to usual (true) division:
190 |
191 | >>> 355/BigFloat(113)
192 | BigFloat.exact('3.14159292035398230088495575221238935', precision=113)
193 | >>> div(355, 113)
194 | BigFloat.exact('3.14159292035398230088495575221238935', precision=113)
195 |
196 | This is useful for a couple of reasons: one reason is that it makes it
197 | possible to use ``div(x, y)`` in contexts where a :class:`BigFloat` result is
198 | desired but where one or both of ``x`` and ``y`` might be an integer or float.
199 | But a more important reason is that these functions, like the :class:`BigFloat`
200 | constructor, accept an extra ``context`` keyword argument giving a
201 | context for the operation::
202 |
203 | >>> div(355, 113, context=single_precision)
204 | BigFloat.exact('3.14159298', precision=24)
205 |
206 | Similarly, the :func:`sub` function corresponds to Python's subtraction
207 | operation. To fully appreciate some of the subtleties of the ways
208 | that binary arithmetic operations might be performed, note the
209 | difference in the results of the following:
210 |
211 | >>> x = 10**16+1 # integer, not exactly representable as a float
212 | >>> y = 10**16. # 10.**16 is exactly representable as a float
213 | >>> x - y
214 | 0.0
215 | >>> BigFloat(x, double_precision) - BigFloat(y, double_precision)
216 | BigFloat.exact('0', precision=53)
217 | >>> sub(x, y, double_precision)
218 | BigFloat.exact('1.0000000000000000', precision=53)
219 |
220 | For the first subtraction, the integer is first converted to a float,
221 | losing accuracy, and then the subtraction is performed, giving a
222 | result of 0.0. The second case is similar: ``x`` and ``y`` are both
223 | explicitly converted to :class:`BigFloat` instances, and the conversion of
224 | ``x`` again loses precision. In the third case, ``x`` and ``y`` are
225 | *implicitly* converted to :class:`BigFloat` instances, and that conversion is
226 | exact, so the subtraction produces exactly the right answer.
227 |
228 | Comparisons between :class:`BigFloat` instances and integers or floats also
229 | behave as you'd expect them to; for these, there's no need for a
230 | corresponding function.
231 |
232 | Mathematical functions
233 | ^^^^^^^^^^^^^^^^^^^^^^
234 |
235 | The :mod:`bigfloat` package provides a number of standard mathematical
236 | functions. These functions follow the same rules as the arithmetic
237 | operations above:
238 |
239 | - the arguments can be integers, floats or :class:`BigFloat` instances
240 |
241 | - integers and float arguments are converted exactly to :class:`BigFloat`
242 | instances before the function is applied
243 |
244 | - the result is a :class:`BigFloat` instance, with the precision of
245 | the result, and the rounding mode used to obtain the result, taken
246 | from the current context.
247 |
248 | - attributes of the current context can be overridden by providing
249 | an additional ``context`` keyword argument.
250 |
251 | Here are some examples::
252 |
253 | >>> sqrt(1729, context=RoundTowardZero)
254 | BigFloat.exact('41.5812457725835818902802091854716460', precision=113)
255 | >>> sqrt(1729, context=RoundTowardPositive)
256 | BigFloat.exact('41.5812457725835818902802091854716521', precision=113)
257 | >>> atanh(0.5, context=precision(20))
258 | BigFloat.exact('0.54930592', precision=20)
259 | >>> const_catalan(precision(1000))
260 | BigFloat.exact('0.9159655941772190150546035149323841107741493742816721342664
261 | 9811962176301977625476947935651292611510624857442261919619957903589880332585
262 | 9059431594737481158406995332028773319460519038727478164087865909024706484152
263 | 1630002287276409423882599577415088163974702524820115607076448838078733704899
264 | 00864775113226027', precision=1000)
265 | >>> 4*exp(-const_pi()/2/agm(1, pow(10, -100)))
266 | BigFloat.exact('1.00000000000000000000000000000000730e-100', precision=113)
267 |
268 | For a full list of the supported functions, see the :ref:`standard functions`
269 | section of the :ref:`api reference`.
270 |
271 | Controlling the precision and rounding mode
272 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
273 |
274 | We've seen one way of controlling precision and rounding mode, via the
275 | ``context`` keyword argument. There's another way that's often more
276 | convenient, especially when a single context change is supposed to apply to
277 | multiple operations: contexts can be used directly in Python's :ref:`with
278 | ` statement.
279 |
280 | For example, here we compute high-precision upper and lower-bounds for
281 | the thousandth harmonic number:
282 |
283 | >>> with precision(100):
284 | ... with RoundTowardNegative: # lower bound
285 | ... lower_bound = sum(div(1, n) for n in range(1, 1001))
286 | ... with RoundTowardPositive: # upper bound
287 | ... upper_bound = sum(div(1, n) for n in range(1, 1001))
288 | ...
289 | >>> lower_bound
290 | BigFloat.exact('7.4854708605503449126565182015873', precision=100)
291 | >>> upper_bound
292 | BigFloat.exact('7.4854708605503449126565182077593', precision=100)
293 |
294 | The effect of the with statement is to change the current context for
295 | the duration of the with block; when the block exits, the previous
296 | context is restored. With statements can be nested, as seen above.
297 | Let's double-check the above results using the asymptotic formula for
298 | the nth harmonic number [#harmonic]_:
299 |
300 | >>> n = 1000
301 | >>> with precision(100):
302 | ... approx = log(n) + const_euler() + div(1, 2*n) - 1/(12*sqr(n))
303 | ...
304 | >>> approx
305 | BigFloat.exact('7.4854708605503365793271531207983', precision=100)
306 |
307 | The error in this approximation should be approximately -1/(120*n**4).
308 | Let's check it:
309 |
310 | >>> error = approx - lower_bound
311 | >>> error
312 | BigFloat.exact('-8.33332936508078900174283813097652403e-15', precision=113)
313 | >>> -1/(120*pow(n, 4))
314 | BigFloat.exact('-8.33333333333333333333333333333333391e-15', precision=113)
315 |
316 | A more permanent change to the context can be effected using the
317 | :func:`setcontext` function, which takes a single argument of type
318 | :class:`Context`:
319 |
320 | >>> setcontext(precision(30))
321 | >>> sqrt(2)
322 | BigFloat.exact('1.4142135624', precision=30)
323 | >>> setcontext(RoundTowardZero)
324 | >>> sqrt(2)
325 | BigFloat.exact('1.4142135605', precision=30)
326 |
327 | An important point here is that in any place that a context is used,
328 | only the attributes specified by that context are changed. For
329 | example, the context ``precision(30)`` only has the ``precision``
330 | attribute, so only that attribute is affected by the :func:`setcontext`
331 | call; the other attributes are not changed. Similarly, the
332 | ``setcontext(RoundTowardZero)`` line above doesn't affect the
333 | precision.
334 |
335 | There's a :data:`DefaultContext` constant giving the default context, so
336 | you can always restore the original default context as follows:
337 |
338 | >>> setcontext(DefaultContext)
339 |
340 | .. note::
341 |
342 | If :func:`setcontext` is used within a with statement, its effects
343 | only last for the duration of the block following the with
344 | statement.
345 |
346 |
347 | Flags
348 | ^^^^^
349 |
350 | The :mod:`bigfloat` package also provides five global flags: 'Inexact',
351 | 'Overflow', 'ZeroDivision', 'Underflow', and 'NanFlag', along with methods to
352 | set and test these flags:
353 |
354 | >>> set_flagstate(set()) # clear all flags
355 | >>> get_flagstate()
356 | set()
357 | >>> exp(10**100)
358 | BigFloat.exact('inf', precision=113)
359 | >>> get_flagstate()
360 | {'Overflow', 'Inexact'}
361 |
362 | These flags show that overflow occurred, and that the given result
363 | (infinity) was inexact. The flags are sticky: none of the standard
364 | operations ever clears a flag:
365 |
366 |
367 | >>> sqrt(2)
368 | BigFloat.exact('1.41421356237309504880168872420969798', precision=113)
369 | >>> get_flagstate() # overflow flag still set from the exp call
370 | {'Overflow', 'Inexact'}
371 | >>> set_flagstate(set()) # clear all flags
372 | >>> sqrt(2)
373 | BigFloat.exact('1.41421356237309504880168872420969798', precision=113)
374 | >>> get_flagstate() # sqrt only sets the inexact flag
375 | {'Inexact'}
376 |
377 | The functions :func:`clear_flag`, :func:`set_flag` and
378 | :func:`test_flag` allow clearing, setting and testing of individual
379 | flags.
380 |
381 | Support for these flags is preliminary, and the API may change in
382 | future versions.
383 |
384 |
385 | .. rubric:: Footnotes
386 |
387 | .. [#harmonic] See http://mathworld.wolfram.com/HarmonicNumber.html
388 |
--------------------------------------------------------------------------------
/cmpfr.pxd:
--------------------------------------------------------------------------------
1 | # Copyright 2009--2019 Mark Dickinson.
2 | #
3 | # This file is part of the bigfloat package.
4 | #
5 | # The bigfloat package is free software: you can redistribute it and/or modify
6 | # it under the terms of the GNU Lesser General Public License as published by
7 | # the Free Software Foundation, either version 3 of the License, or (at your
8 | # option) any later version.
9 | #
10 | # The bigfloat package is distributed in the hope that it will be useful, but
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 | # for more details.
14 | #
15 | # You should have received a copy of the GNU Lesser General Public License
16 | # along with the bigfloat package. If not, see .
17 |
18 | # mpfr.h needs declarations from stdio.h.
19 | cdef extern from "stdio.h":
20 | pass
21 |
22 | cimport cgmp
23 |
24 | cdef extern from "mpfr.h":
25 | # MPFR type declarations
26 | ctypedef int mpfr_prec_t
27 | ctypedef int mpfr_sign_t
28 | ctypedef unsigned int mpfr_flags_t
29 | ctypedef cgmp.mp_exp_t mpfr_exp_t
30 |
31 | ctypedef struct __mpfr_struct:
32 | mpfr_prec_t _mpfr_prec
33 | mpfr_sign_t _mpfr_sign
34 | mpfr_exp_t _mpfr_exp
35 | cgmp.mp_limb_t *_mpfr_d
36 |
37 | # We don't export the mpfr_t type; it's not useful for Cython code, since
38 | # Cython (as of version 0.14.1) doesn't seem to understand it properly: the
39 | # generated C code includes temporary variables of type mpfr_t and
40 | # assignments from one object of type mpfr_t to another, which isn't valid
41 | # C. So we comment out the definition here in order to catch any
42 | # accidental declarations using mpfr_t below.
43 |
44 | # ctypedef __mpfr_struct mpfr_t[1]
45 | ctypedef __mpfr_struct *mpfr_ptr
46 |
47 | # MPFR rounding modes
48 | ctypedef enum mpfr_rnd_t:
49 | MPFR_RNDN = 0
50 | MPFR_RNDZ
51 | MPFR_RNDU
52 | MPFR_RNDD
53 | MPFR_RNDA
54 | MPFR_RNDF
55 | MPFR_RNDNA = -1
56 |
57 | # Free cache policy
58 | ctypedef enum mpfr_free_cache_t:
59 | MPFR_FREE_LOCAL_CACHE = 1
60 | MPFR_FREE_GLOBAL_CACHE = 2
61 |
62 | # Limits
63 | mpfr_prec_t MPFR_PREC_MIN
64 | mpfr_prec_t MPFR_PREC_MAX
65 |
66 | mpfr_exp_t MPFR_EMIN_DEFAULT
67 | mpfr_exp_t MPFR_EMAX_DEFAULT
68 |
69 | # Flags
70 | mpfr_flags_t MPFR_FLAGS_UNDERFLOW
71 | mpfr_flags_t MPFR_FLAGS_OVERFLOW
72 | mpfr_flags_t MPFR_FLAGS_NAN
73 | mpfr_flags_t MPFR_FLAGS_INEXACT
74 | mpfr_flags_t MPFR_FLAGS_ERANGE
75 | mpfr_flags_t MPFR_FLAGS_DIVBY0
76 | mpfr_flags_t MPFR_FLAGS_ALL
77 |
78 |
79 | ###########################################################################
80 | # 5.1 Initialization Functions
81 | ###########################################################################
82 |
83 | void mpfr_init2(mpfr_ptr x, mpfr_prec_t prec)
84 | void mpfr_clear(mpfr_ptr x)
85 | void mpfr_init(mpfr_ptr x)
86 | void mpfr_set_default_prec(mpfr_prec_t prec)
87 | mpfr_prec_t mpfr_get_default_prec()
88 | void mpfr_set_prec(mpfr_ptr x, mpfr_prec_t prec)
89 | mpfr_prec_t mpfr_get_prec(mpfr_ptr x)
90 |
91 |
92 | ###########################################################################
93 | # 5.2 Assignment Functions
94 | ###########################################################################
95 |
96 | int mpfr_set(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
97 | int mpfr_set_ui(mpfr_ptr rop, unsigned long int op, mpfr_rnd_t rnd)
98 | int mpfr_set_si(mpfr_ptr rop, long int op, mpfr_rnd_t rnd)
99 | int mpfr_set_d(mpfr_ptr rop, double op, mpfr_rnd_t rnd)
100 | int mpfr_set_z(mpfr_ptr rop, cgmp.mpz_ptr op, mpfr_rnd_t rnd)
101 | int mpfr_set_ui_2exp(
102 | mpfr_ptr rop, unsigned long int op, mpfr_exp_t e, mpfr_rnd_t rnd
103 | )
104 | int mpfr_set_si_2exp(
105 | mpfr_ptr rop, long int op, mpfr_exp_t e, mpfr_rnd_t rnd
106 | )
107 | int mpfr_set_z_2exp(
108 | mpfr_ptr rop, cgmp.mpz_ptr op, mpfr_exp_t e, mpfr_rnd_t rnd
109 | )
110 | int mpfr_set_str(
111 | mpfr_ptr rop, const char *s, int base, mpfr_rnd_t rnd
112 | )
113 | int mpfr_strtofr(
114 | mpfr_ptr rop, const char *nptr, char **endptr, int base, mpfr_rnd_t rnd
115 | )
116 | void mpfr_set_nan(mpfr_ptr x)
117 | void mpfr_set_inf(mpfr_ptr x, int sign)
118 | void mpfr_set_zero(mpfr_ptr x, int sign)
119 | void mpfr_swap(mpfr_ptr x, mpfr_ptr y)
120 |
121 |
122 | ###########################################################################
123 | # 5.4 Conversion Functions
124 | ###########################################################################
125 |
126 | double mpfr_get_d(mpfr_ptr op, mpfr_rnd_t rnd)
127 | long int mpfr_get_si(mpfr_ptr op, mpfr_rnd_t rnd)
128 | unsigned long int mpfr_get_ui(mpfr_ptr op, mpfr_rnd_t rnd)
129 | double mpfr_get_d_2exp(long int *exp, mpfr_ptr op, mpfr_rnd_t rnd)
130 | int mpfr_frexp(mpfr_exp_t *exp, mpfr_ptr y, mpfr_ptr x, mpfr_rnd_t rnd)
131 | mpfr_exp_t mpfr_get_z_2exp(cgmp.mpz_ptr rop, mpfr_ptr op)
132 | int mpfr_get_z(cgmp.mpz_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
133 |
134 | char * mpfr_get_str(
135 | char *str, mpfr_exp_t *expptr, int b,
136 | size_t n, mpfr_ptr op, mpfr_rnd_t rnd
137 | )
138 | void mpfr_free_str(char *str)
139 | int mpfr_fits_ulong_p(mpfr_ptr x, mpfr_rnd_t rnd)
140 | int mpfr_fits_slong_p(mpfr_ptr x, mpfr_rnd_t rnd)
141 |
142 |
143 | ###########################################################################
144 | # 5.5 Basic Arithmetic Functions
145 | ###########################################################################
146 |
147 | int mpfr_add(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
148 | int mpfr_sub(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
149 | int mpfr_mul(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
150 | int mpfr_sqr(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
151 | int mpfr_div(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
152 | int mpfr_sqrt(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
153 | int mpfr_rec_sqrt(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
154 | int mpfr_cbrt(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
155 | int mpfr_rootn_ui(
156 | mpfr_ptr top, mpfr_ptr op, unsigned long int k, mpfr_rnd_t rnd
157 | )
158 | int mpfr_root(
159 | mpfr_ptr top, mpfr_ptr op, unsigned long int k, mpfr_rnd_t rnd
160 | )
161 | int mpfr_pow(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
162 | int mpfr_neg(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
163 | int mpfr_abs(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
164 | int mpfr_dim(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
165 |
166 |
167 | ###########################################################################
168 | # 5.6 Comparison Functions
169 | ###########################################################################
170 |
171 | int mpfr_cmp(mpfr_ptr op1, mpfr_ptr op2)
172 | int mpfr_cmpabs(mpfr_ptr op1, mpfr_ptr op2)
173 | int mpfr_nan_p(mpfr_ptr op)
174 | int mpfr_inf_p(mpfr_ptr op)
175 | int mpfr_number_p(mpfr_ptr op)
176 | int mpfr_zero_p(mpfr_ptr op)
177 | int mpfr_regular_p(mpfr_ptr op)
178 | int mpfr_sgn(mpfr_ptr op)
179 | int mpfr_greater_p(mpfr_ptr op1, mpfr_ptr op2)
180 | int mpfr_greaterequal_p(mpfr_ptr op1, mpfr_ptr op2)
181 | int mpfr_less_p(mpfr_ptr op1, mpfr_ptr op2)
182 | int mpfr_lessequal_p(mpfr_ptr op1, mpfr_ptr op2)
183 | int mpfr_equal_p(mpfr_ptr op1, mpfr_ptr op2)
184 | int mpfr_lessgreater_p(mpfr_ptr op1, mpfr_ptr op2)
185 | int mpfr_unordered_p(mpfr_ptr op1, mpfr_ptr op2)
186 |
187 |
188 | ###########################################################################
189 | # 5.7 Special Functions
190 | ###########################################################################
191 |
192 | int mpfr_log(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
193 | int mpfr_log_ui(mpfr_ptr rop, unsigned long op, mpfr_rnd_t rnd)
194 | int mpfr_log2(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
195 | int mpfr_log10(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
196 |
197 | int mpfr_log1p(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
198 |
199 | int mpfr_exp(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
200 | int mpfr_exp2(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
201 | int mpfr_exp10(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
202 |
203 | int mpfr_expm1(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
204 |
205 | int mpfr_cos(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
206 | int mpfr_sin(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
207 | int mpfr_tan(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
208 |
209 | int mpfr_sin_cos(mpfr_ptr sop, mpfr_ptr cop, mpfr_ptr op, mpfr_rnd_t rnd)
210 |
211 | int mpfr_sec(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
212 | int mpfr_csc(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
213 | int mpfr_cot(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
214 |
215 | int mpfr_acos(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
216 | int mpfr_asin(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
217 | int mpfr_atan(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
218 |
219 | int mpfr_atan2(mpfr_ptr rop, mpfr_ptr y, mpfr_ptr x, mpfr_rnd_t rnd)
220 |
221 | int mpfr_cosh(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
222 | int mpfr_sinh(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
223 | int mpfr_tanh(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
224 |
225 | int mpfr_sinh_cosh(mpfr_ptr sop, mpfr_ptr cop, mpfr_ptr op, mpfr_rnd_t rnd)
226 |
227 | int mpfr_sech(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
228 | int mpfr_csch(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
229 | int mpfr_coth(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
230 |
231 | int mpfr_acosh(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
232 | int mpfr_asinh(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
233 | int mpfr_atanh(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
234 |
235 | int mpfr_fac_ui(mpfr_ptr rop, unsigned long int op, mpfr_rnd_t rnd)
236 |
237 | int mpfr_eint(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
238 | int mpfr_li2(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
239 | int mpfr_gamma(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
240 | int mpfr_gamma_inc(mpfr_ptr rop, mpfr_ptr op, mpfr_ptr op2, mpfr_rnd_t rnd)
241 | int mpfr_lngamma(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
242 | int mpfr_lgamma(mpfr_ptr rop, int *signp, mpfr_ptr op, mpfr_rnd_t rnd)
243 | int mpfr_digamma(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
244 | int mpfr_beta(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
245 | int mpfr_zeta(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
246 | int mpfr_zeta_ui(mpfr_ptr rop, unsigned long int op, mpfr_rnd_t rnd)
247 | int mpfr_erf(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
248 | int mpfr_erfc(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
249 | int mpfr_j0(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
250 | int mpfr_j1(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
251 | int mpfr_jn(mpfr_ptr rop, long int n, mpfr_ptr op, mpfr_rnd_t rnd)
252 | int mpfr_y0(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
253 | int mpfr_y1(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
254 | int mpfr_yn(mpfr_ptr rop, long int n, mpfr_ptr op, mpfr_rnd_t rnd)
255 |
256 | int mpfr_fma(
257 | mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_ptr op3, mpfr_rnd_t rnd
258 | )
259 | int mpfr_fms(
260 | mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_ptr op3, mpfr_rnd_t rnd
261 | )
262 | int mpfr_fmma(
263 | mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_ptr op3, mpfr_ptr op4,
264 | mpfr_rnd_t rnd
265 | )
266 | int mpfr_fmms(
267 | mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_ptr op3, mpfr_ptr op4,
268 | mpfr_rnd_t rnd
269 | )
270 | int mpfr_agm(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
271 | int mpfr_hypot(mpfr_ptr rop, mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd)
272 |
273 | int mpfr_ai(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
274 |
275 | int mpfr_const_log2(mpfr_ptr rop, mpfr_rnd_t rnd)
276 | int mpfr_const_pi(mpfr_ptr rop, mpfr_rnd_t rnd)
277 | int mpfr_const_euler(mpfr_ptr rop, mpfr_rnd_t rnd)
278 | int mpfr_const_catalan(mpfr_ptr rop, mpfr_rnd_t rnd)
279 |
280 | void mpfr_free_cache()
281 | void mpfr_free_cache2(mpfr_free_cache_t way)
282 | void mpfr_free_pool()
283 | int mpfr_mp_memory_cleanup()
284 |
285 | int mpfr_sum(
286 | mpfr_ptr rop, const mpfr_ptr tab[], unsigned long int n,
287 | mpfr_rnd_t rnd
288 | )
289 |
290 | ###########################################################################
291 | # 5.9 Formatted Output Functions
292 | ###########################################################################
293 |
294 | int mpfr_asprintf(char **str, const char *template, ...)
295 |
296 | ###########################################################################
297 | # 5.10 Integer and Remainder Related Functions
298 | ###########################################################################
299 |
300 | int mpfr_rint(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
301 | int mpfr_ceil(mpfr_ptr rop, mpfr_ptr op)
302 | int mpfr_floor(mpfr_ptr rop, mpfr_ptr op)
303 | int mpfr_round(mpfr_ptr rop, mpfr_ptr op)
304 | int mpfr_roundeven(mpfr_ptr rop, mpfr_ptr op)
305 | int mpfr_trunc(mpfr_ptr rop, mpfr_ptr op)
306 |
307 | int mpfr_rint_ceil(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
308 | int mpfr_rint_floor(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
309 | int mpfr_rint_round(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
310 | int mpfr_rint_roundeven(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
311 | int mpfr_rint_trunc(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
312 |
313 | int mpfr_frac(mpfr_ptr rop, mpfr_ptr op, mpfr_rnd_t rnd)
314 | int mpfr_modf(mpfr_ptr iop, mpfr_ptr fop, mpfr_ptr op, mpfr_rnd_t rnd)
315 |
316 | int mpfr_fmod(mpfr_ptr r, mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd)
317 | int mpfr_fmodquo(
318 | mpfr_ptr r, long int *q, mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd
319 | )
320 | int mpfr_remainder(mpfr_ptr r, mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd)
321 | int mpfr_remquo(
322 | mpfr_ptr r, long int *q, mpfr_ptr x, mpfr_ptr y, mpfr_rnd_t rnd
323 | )
324 | int mpfr_integer_p(mpfr_ptr op)
325 |
326 |
327 | ###########################################################################
328 | # 5.11 Rounding Related Functions
329 | ###########################################################################
330 |
331 | void mpfr_set_default_rounding_mode(mpfr_rnd_t rnd)
332 | mpfr_rnd_t mpfr_get_default_rounding_mode()
333 | int mpfr_prec_round(mpfr_ptr x, mpfr_prec_t prec, mpfr_rnd_t rnd)
334 | int mpfr_can_round(
335 | mpfr_ptr b, mpfr_exp_t err,
336 | mpfr_rnd_t rnd1, mpfr_rnd_t rnd2,
337 | mpfr_prec_t prec
338 | )
339 | mpfr_prec_t mpfr_min_prec(mpfr_ptr x)
340 | const char *mpfr_print_rnd_mode(mpfr_rnd_t rnd)
341 |
342 |
343 | ###########################################################################
344 | # 5.12 Miscellaneous Functions
345 | ###########################################################################
346 |
347 | void mpfr_nexttoward(mpfr_ptr rop, mpfr_ptr op)
348 | void mpfr_nextabove(mpfr_ptr op)
349 | void mpfr_nextbelow(mpfr_ptr op)
350 | int mpfr_min(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
351 | int mpfr_max(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
352 | mpfr_exp_t mpfr_get_exp(mpfr_ptr x)
353 | int mpfr_set_exp(mpfr_ptr x, mpfr_exp_t exp)
354 | int mpfr_signbit(mpfr_ptr op)
355 | int mpfr_setsign(mpfr_ptr rop, mpfr_ptr op, int s, mpfr_rnd_t rnd)
356 | int mpfr_copysign(mpfr_ptr rop, mpfr_ptr op1, mpfr_ptr op2, mpfr_rnd_t rnd)
357 | const char *mpfr_get_version()
358 | int MPFR_VERSION
359 | int MPFR_VERSION_MAJOR
360 | int MPFR_VERSION_MINOR
361 | int MPFR_VERSION_PATCHLEVEL
362 | const char *MPFR_VERSION_STRING
363 | int MPFR_VERSION_NUM(int major, int minor, int patchlevel)
364 | const char *mpfr_get_patches()
365 | int mpfr_buildopt_tls_p()
366 | int mpfr_buildopt_float128_p()
367 | int mpfr_buildopt_decimal_p()
368 | int mpfr_buildopt_gmpinternals_p()
369 | int mpfr_buildopt_sharedcache_p()
370 | const char *mpfr_buildopt_tune_case()
371 |
372 |
373 | ###########################################################################
374 | # 5.13 Exception Related Functions
375 | ###########################################################################
376 |
377 | mpfr_exp_t mpfr_get_emin()
378 | mpfr_exp_t mpfr_get_emax()
379 | int mpfr_set_emin(mpfr_exp_t exp)
380 | int mpfr_set_emax(mpfr_exp_t exp)
381 | mpfr_exp_t mpfr_get_emin_min()
382 | mpfr_exp_t mpfr_get_emin_max()
383 | mpfr_exp_t mpfr_get_emax_min()
384 | mpfr_exp_t mpfr_get_emax_max()
385 | int mpfr_check_range(mpfr_ptr x, int t, mpfr_rnd_t rnd)
386 | int mpfr_subnormalize(mpfr_ptr x, int t, mpfr_rnd_t rnd)
387 |
388 | void mpfr_clear_underflow()
389 | void mpfr_clear_overflow()
390 | void mpfr_clear_divby0()
391 | void mpfr_clear_nanflag()
392 | void mpfr_clear_inexflag()
393 | void mpfr_clear_erangeflag()
394 |
395 | void mpfr_set_underflow()
396 | void mpfr_set_overflow()
397 | void mpfr_set_divby0()
398 | void mpfr_set_nanflag()
399 | void mpfr_set_inexflag()
400 | void mpfr_set_erangeflag()
401 |
402 | void mpfr_clear_flags()
403 |
404 | int mpfr_underflow_p()
405 | int mpfr_overflow_p()
406 | int mpfr_divby0_p()
407 | int mpfr_nanflag_p()
408 | int mpfr_inexflag_p()
409 | int mpfr_erangeflag_p()
410 |
411 | void mpfr_flags_clear(mpfr_flags_t mask)
412 | void mpfr_flags_set(mpfr_flags_t mask)
413 | mpfr_flags_t mpfr_flags_test(mpfr_flags_t mask)
414 | mpfr_flags_t mpfr_flags_save()
415 | void mpfr_flags_restore(mpfr_flags_t flags, mpfr_flags_t mask)
416 |
--------------------------------------------------------------------------------