| [ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
16.3 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_sizeThe number of limbs currently in use, or the negative of that when representing a negative value. Zero is represented by
_mp_sizeand_mp_expboth set to zero, and in that case the_mp_ddata is unused. (In the future_mp_expmight be undefined when representing zero.)_mp_precThe precision of the mantissa, in limbs. In any calculation the aim is to produce
_mp_preclimbs of result (the most significant being non-zero)._mp_dA pointer to the array of limbs which is the absolute value of the mantissa. These are stored “little endian” as per the
mpnfunctions, 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+1limbs 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 withmpf_set_prec._mp_expThe 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.
The _mp_size and _mp_prec fields are int, although the
mp_size_t type is usually a long. The _mp_exp field is
usually long. This is done to make some fields just 32 bits on some 64
bits systems, thereby saving a few bytes of data space but still providing
plenty of precision and a very large 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_sizecount of limbs in use can be less than_mp_precif the value can be represented in less. This means low precision values or small integers stored in a high precisionmpf_tcan still be operated on efficiently._mp_sizecan also be greater than_mp_prec. Firstly a value is allowed to use all of the_mp_prec+1limbs available at_mp_d, and secondly whenmpf_set_prec_rawlowers_mp_precit leaves_mp_sizeunchanged and so the size can be arbitrarily bigger than_mp_prec.- Rounding
All rounding is done on limb boundaries. Calculating
_mp_preclimbs 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_addandmpf_mul. When differing exponents are encountered all that’s needed is to adjust pointers to line up the relevant limbs.Of course
mpf_mul_2expandmpf_div_2expwill 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+1Limbs The extra limb on
_mp_d(_mp_prec+1rather than just_mp_prec) helps when anmpfroutine might get a carry from its operation.mpf_addfor instance will do anmpn_addof_mp_preclimbs. 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_sizebecomes_mp_prec+1.Whenever
_mp_prec+1limbs are held in a variable, the low limb is not needed for the intended precision, only the_mp_prechigh 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_precif 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_setwill retain a full_mp_prec+1limbs if available. This ensures that a variable which has_mp_sizeequal to_mp_prec+1will get its full exact value copied. Strictly speaking this is unnecessary since only_mp_preclimbs are needed for the application’s requested precision, but it’s considered that anmpf_setfrom one variable into another of the same precision ought to produce an exact copy.- Application Precisions
__GMPF_BITS_TO_PRECconverts 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_dis only non-zero and therefore might contain only one bit.__GMPF_PREC_TO_BITSdoes the reverse conversion, and removes the extra limb from_mp_precbefore converting to bits. The net effect of reading back withmpf_get_precis simply the precision rounded up to a multiple ofmp_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_precof 9._mp_dthen gets 10 limbs allocated. Reading back withmpf_get_precwill take_mp_precsubtract 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_tit’s considered simply to be 64 bits, a nice multiple of the limb size.
| [ << ] | [ < ] | [ Up ] | [ > ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
This document was generated on March 31, 2014 using texi2html 5.0.
