crystal
crystal copied to clipboard
Using MPFR for `BigFloat`
The MPFR library addresses several deficiencies in the mpf_*
functions provided by GMP:
- It has proper IEEE 754 semantics, e.g. infinity and accurate rounding;
- It provides definitions for almost all of the mathematical functions we define in
Math
, likesin
and the floating-point manipulation functions; - MPFR floats support arbitrary-precision string conversions (see https://github.com/crystal-lang/crystal/pull/10632#issuecomment-885418088).
So I think we should use that on top of GMP (we cannot replace it because GMP as a whole also provides BigInt
and BigRational
). MPFR provides functions to convert to and from GMP's mpf_t
in case any Crystal code depends on LibGMP::MPF
directly.
I was thinking about how to bridge the differences between our rounding modes and MPFR's. MPFR defines seven:
-
MPFR_RNDN
, equivalent toRoundingMode::TIES_EVEN
-
MPFR_RNDZ
, equivalent toRoundingMode::TO_ZERO
-
MPFR_RNDU
, equivalent toRoundingMode::TO_POSITIVE
-
MPFR_RNDD
, equivalent toRoundingMode::TO_NEGATIVE
-
MPFR_RNDA
, round away from zero, has no Crystal equivalent -
MPFR_RNDF
, faithful rounding, only supported for a subset of operations, has no Crystal equivalent -
MPFR_RNDNA
, internal use only, equivalent toRoundingMode::TIES_EVEN
- the public macro
mpfr_round_nearest_away
emulates this, and fortunately can be ported to Crystal
- the public macro
Those rounding modes are available in almost every operation, where rounding occurs in the least significant bits in the mantissa, not just mpfr_round
(round to integer). There is also a default rounding mode configurable by mpfr_set_default_rounding_mode
, but it doesn't appear to be used by MPFR itself, and is only for the GMP MPF compatibility mode shown here. Thus it would make no sense to bind that function here, because adding MPFR to the standard library implies not using LibGMP::MPF
at all.
I don't think the standard library would enjoy supplying a rounding mode parameter to every method on BigFloat
. So outside of the few rounding-related methods, MPFR_RNDN
should be passed to MPFR. #11097 might mean that we could roll our own default mode.