encodeFloat (J# s# d#) e = encodeDouble# s# d# e}}} This is not the case with the safer `fromRat` function which ensures the Integer falls in the range of the mantissa (see the source code). The problem with `__encodeFloat` and `__encodeDouble` is normative--a matter of design. The current implementation places the responsibility for ensuring that large integers converted to floating point numbers do not overflow or underflow and it is practically impossible (with rounding) to join encoding and decoding and come out with a reasonably equivalent result, as in: {{{ #!html

(uncurry encodeFloat) . decodeFloat}}} (Note: this is a standard problem with floating point. A replacement library could probably do little better.) A replacement library for GMP might use the GMP strategies of including a special bitwise conversion (with appropriate masks) and a hardware-based version. An unconventional solution might perform the rounding manually (but with relatively portable predictability) using interval arithmetic. As for printing GMP numbers, [[GhcFile(libraries/base/GHC/Num.lhs)]] defines a special internal function `jtos` to handle `showsPrec` and `showList` for `Integer` as an instance of the class `Show`. The `jtos` function uses the primitive GMP-based function `quotRemInteger` and performs many conversions from Integer to Int. This is not as efficient as the internal GMP functions, especially for large numbers, because each conversion allocates extra storage for GMP as noted in [wiki:ReplacingGMPNotes#OptimisationOpportunities Replacing GMP -- Optimisation Opportunities]. === GMP Library Implementation === The GMP library, like most multi-precision libraries has a fundamental limitation that might seem odd if you are only familiar with Haskell--not likely, but it bears mention anyway! GMP functions require that their operands be separate entities. (Remember: an operation such as `a + b` has three entities: the two operands and the result.) That is, if you want to add `mpz_t a` to `mpz_t b`, and place the result in `mpz_t c`, you are fine but if you try to add `a` to `a` you will run into trouble. (The problem is, the multi-precision integer library functions are designed so the operands cannot alias; this is more of a problem for complex operations such as multiplication than simple operations like addition.) This limitation might be overcome by designing the API differently, for example: 1. compare the operands in Haskell, Cmm or whatever before you pass them to the _add function; 2. if the operands are the same, create a separate copy of the operand 3. -- you are o.k. for the case where two operands cannot be the same. For the case where one of the operands and the result is the same you would have to check outside the general Haskell, Cmm or whatever function wrapping the _add function--you would seem to need a higher level construct. This is already handled by the Haskell language, since `Integer`s are subject to the same functional properties as other non-mutable variables. There does seem to be a problem with `Int`s and `Integer`s in GHCi--I (PDT) am not sure whether this is a naming problem (the name after `let` is a binding-name) or an evaluation problem. Here is an example: {{{ #!html

(in GHCi) > let m_integer = 123456789 :: Integer > let n_integer = m_integer + m_integer -- this will show o.k., but the implementation involves *always* making extra temporaries > n_integer 246913578 -- a = a + a > let m_integer = m_integer + m_integer --"m_integer" after "let" here is a new binding > let n_integer = m_integer + m_integer -- this will be fine until you try to evaluate it: > n_integer *** Exception: stack overflow -- now, try the same thing with plain Ints: -- this will default to an Int > let a = 5 > let a = a + a > let b = a + a > b *** Exception: stack overflow}}}