DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 

(gmp.info.gz) Float Internals

Info Catalog (gmp.info.gz) Rational Internals (gmp.info.gz) Internals (gmp.info.gz) Raw Output Internals
 
 Float Internals
 ===============
 
 Efficient calculation is the primary aim of GMP floats and the use of
 whole limbs and simple rounding facilitates this.
 
    `mpf_t' floats have a variable precision mantissa and a single
 machine word signed exponent.  The mantissa is represented using sign
 and magnitude.
 
         most                   least
      significant            significant
         limb                   limb
      
                                  _mp_d
       |---- _mp_exp --->           |
        _____ _____ _____ _____ _____
       |_____|_____|_____|_____|_____|
                         . <------------ radix point
      
        <-------- _mp_size --------->
 
 The fields are as follows.
 
 `_mp_size'
      The number of limbs currently in use, or the negative of that when
      representing a negative value.  Zero is represented by `_mp_size'
      and `_mp_exp' both set to zero, and in that case the `_mp_d' data
      is unused.  (In the future `_mp_exp' might be undefined when
      representing zero.)
 
 `_mp_prec'
      The precision of the mantissa, in limbs.  In any calculation the
      aim is to produce `_mp_prec' limbs of result (the most significant
      being non-zero).
 
 `_mp_d'
      A pointer to the array of limbs which is the absolute value of the
      mantissa.  These are stored "little endian" as per the `mpn'
      functions, so `_mp_d[0]' is the least significant limb and
      `_mp_d[ABS(_mp_size)-1]' the most significant.
 
      The most significant limb is always non-zero, but there are no
      other restrictions on its value, in particular the highest 1 bit
      can be anywhere within the limb.
 
      `_mp_prec+1' limbs are allocated to `_mp_d', the extra limb being
      for convenience (see below).  There are no reallocations during a
      calculation, only in a change of precision with `mpf_set_prec'.
 
 `_mp_exp'
      The exponent, in limbs, determining the location of the implied
      radix point.  Zero means the radix point is just above the most
      significant limb.  Positive values mean a radix point offset
      towards the lower limbs and hence a value >= 1, as for example in
      the diagram above.  Negative exponents mean a radix point further
      above the highest limb.
 
      Naturally the exponent can be any value, it doesn't have to fall
      within the limbs as the diagram shows, it can be a long way above
      or a long way below.  Limbs other than those included in the
      `{_mp_d,_mp_size}' data are treated as zero.
 
    `_mp_size' and `_mp_prec' are `int', although `mp_size_t' is usually
 a `long'.  This is done to make the fields just 32 bits on some 64 bits
 systems, thereby saving a few bytes of data space but still providing
 plenty of range.
 
 
 The following various points should be noted.
 
 Low Zeros
      The least significant limbs `_mp_d[0]' etc can be zero, though
      such low zeros can always be ignored.  Routines likely to produce
      low zeros check and avoid them to save time in subsequent
      calculations, but for most routines they're quite unlikely and
      aren't checked.
 
 Mantissa Size Range
      The `_mp_size' count of limbs in use can be less than `_mp_prec' if
      the value can be represented in less.  This means low precision
      values or small integers stored in a high precision `mpf_t' can
      still be operated on efficiently.
 
      `_mp_size' can also be greater than `_mp_prec'.  Firstly a value is
      allowed to use all of the `_mp_prec+1' limbs available at `_mp_d',
      and secondly when `mpf_set_prec_raw' lowers `_mp_prec' it leaves
      `_mp_size' unchanged and so the size can be arbitrarily bigger than
      `_mp_prec'.
 
 Rounding
      All rounding is done on limb boundaries.  Calculating `_mp_prec'
      limbs with the high non-zero will ensure the application requested
      minimum precision is obtained.
 
      The use of simple "trunc" rounding towards zero is efficient,
      since there's no need to examine extra limbs and increment or
      decrement.
 
 Bit Shifts
      Since the exponent is in limbs, there are no bit shifts in basic
      operations like `mpf_add' and `mpf_mul'.  When differing exponents
      are encountered all that's needed is to adjust pointers to line up
      the relevant limbs.
 
      Of course `mpf_mul_2exp' and `mpf_div_2exp' will require bit
      shifts, but the choice is between an exponent in limbs which
      requires shifts there, or one in bits which requires them almost
      everywhere else.
 
 Use of `_mp_prec+1' Limbs
      The extra limb on `_mp_d' (`_mp_prec+1' rather than just
      `_mp_prec') helps when an `mpf' routine might get a carry from its
      operation.  `mpf_add' for instance will do an `mpn_add' of
      `_mp_prec' limbs.  If there's no carry then that's the result, but
      if there is a carry then it's stored in the extra limb of space and
      `_mp_size' becomes `_mp_prec+1'.
 
      Whenever `_mp_prec+1' limbs are held in a variable, the low limb
      is not needed for the intended precision, only the `_mp_prec' high
      limbs.  But zeroing it out or moving the rest down is unnecessary.
      Subsequent routines reading the value will simply take the high
      limbs they need, and this will be `_mp_prec' if their target has
      that same precision.  This is no more than a pointer adjustment,
      and must be checked anyway since the destination precision can be
      different from the sources.
 
      Copy functions like `mpf_set' will retain a full `_mp_prec+1' limbs
      if available.  This ensures that a variable which has `_mp_size'
      equal to `_mp_prec+1' will get its full exact value copied.
      Strictly speaking this is unnecessary since only `_mp_prec' limbs
      are needed for the application's requested precision, but it's
      considered that an `mpf_set' from one variable into another of the
      same precision ought to produce an exact copy.
 
 Application Precisions
      `__GMPF_BITS_TO_PREC' converts an application requested precision
      to an `_mp_prec'.  The value in bits is rounded up to a whole limb
      then an extra limb is added since the most significant limb of
      `_mp_d' is only non-zero and therefore might contain only one bit.
 
      `__GMPF_PREC_TO_BITS' does the reverse conversion, and removes the
      extra limb from `_mp_prec' before converting to bits.  The net
      effect of reading back with `mpf_get_prec' is simply the precision
      rounded up to a multiple of `mp_bits_per_limb'.
 
      Note that the extra limb added here for the high only being
      non-zero is in addition to the extra limb allocated to `_mp_d'.
      For example with a 32-bit limb, an application request for 250
      bits will be rounded up to 8 limbs, then an extra added for the
      high being only non-zero, giving an `_mp_prec' of 9.  `_mp_d' then
      gets 10 limbs allocated.  Reading back with `mpf_get_prec' will
      take `_mp_prec' subtract 1 limb and multiply by 32, giving 256
      bits.
 
      Strictly speaking, the fact the high limb has at least one bit
      means that a float with, say, 3 limbs of 32-bits each will be
      holding at least 65 bits, but for the purposes of `mpf_t' it's
      considered simply to be 64 bits, a nice multiple of the limb size.
 
Info Catalog (gmp.info.gz) Rational Internals (gmp.info.gz) Internals (gmp.info.gz) Raw Output Internals
automatically generated byinfo2html