The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Data::Float::DoubleDouble - human-readable representation of the "double-double" long double

AIM

  Mostly, one would use Data::Float to do what this module does.
  But that module doesn't work with the powerpc long double,
  which uses a 'double-double' arrangement ... hence, this module.

  Given a double-double value, we aim to be able to:
   1) Convert that NV to its internal packed hex form;
   2) Convert the packed hex form of 1) back to the original value;
   3) Convert that NV to a more human-readable packed hex form,
      similar to what Data::Float's float_hex function achieves;
   4) Convert the packed hex form of 3) back to the original value;

   For 1) we use NV2H().
   For 2) we use H2NV().
   For 3) we use float_H().
   For 4) we use H_float().

   We also have float_B and B_float which are the base 2
   equivalents of float_H and H_float.

FUNCTIONS

  #############################################
  $hex = NV2H($nv);

   Unpacks the NV to a string of 32 hex characters.
   The first 16 characters relate to the value of the most significant
   double:
    Characters 1 to 3 (incl) embody the sign of the mantissa, the value 
    of the exponent, and the value (0 or 1) of the implied leading bit.
    Characters 4 to 16 (incl) embody the value of the 52-bit mantissa.

   The second 16 characters (17 to 32) relate to the value of the least
   siginificant double:
    Characters 17 to 19 (incl) embody the sign of the mantissa, the 
    value of the exponent, and the value (0 or 1) of the implied
    leading bit.
    Characters 20 to 32 (incl) embody the value of the 52-bit mantissa.

   For a more human-readable hex representation, use float_H().
  #############################################
  $nv = H2NV($hex);

   For $hex written in the format returned by NV2H, H2NV($hex)
   returns the NV.
  #############################################
  $hex = D2H($nv);

   Treats the NV as a double and returns a string of 16 hex characters.
   Characters 1 to 3 (incl) embody the sign of the mantissa, the value
   (0 or 1) of the implied leading bit and the value of the exponent.
   Characters 4 to 16 (incl) embody the value of the 52-bit mantissa
   of the first double.
  #############################################
  $nv = H2D($hex);

   For $hex written in the format returned by D2H, H2D($hex) returns
   the NV.
  #############################################
  $readable_hex = float_H($nv); # Aliased to float_hex

   For *most* NVs, returns a 106-bit hex representation of the NV
   (long double) $nv in the format
   s0xd.hhhhhhhhhhhhhhhhhhhhhhhhhhhpe where:
    s is the sign (either '-' or '+')
    0x is literally "0x"
    d is the leading (first) bit of the number (either '1' or '0')
    . is literally "." (the decimal point)
    hhhhhhhhhhhhhhhhhhhhhhhhhhh is a string of 27 hex digits
                                representing the remaining 105 bits
                                of the mantissa.
    p is a literal "p" that separates mantissa from exponent
    e is the (signed) exponent

   The keen mind will have realised that 27 hex digits encode 108
   (not 105) bits. However, the last 3 bits are to be ignored and
   will always be zero for a 106-bit float. Thus the 27th hex
   character for a 106-bit float will either be "8" (representing
   a "1") or "0" (representing a "0") for the 106th bit.

   BUT: Some NV values encapsulate a value that require more than
        106 bits in order to be correctly represented.
        If the string that float_H returns is larger than as
        described above, then it will, however,  have returned a
        string that contains the *minimum* number of characters
        needed to accurately represent the given value.
        As an extreme example: the double-double arrangement can
        represent the value 2**1023 + 2**-1074, but to express
        that value as a stream of bits requires 2098 bits, and to
        express that value in the format that float_H returns
        requires 526 hex characters (all of which are zero, except
        for the first and the last). When you add the sign, radix
        point, exponent, etc., the float_H representation of that
        value consists of 535 characters.

  #############################################
  $nv = H_float($hex);

   For $hex written in the format returned by float_H(), returns
   the NV that corresponds to $hex.
  #############################################  
  @bin = float_B($nv);

   Returns the sign, the mantissa (as a base 2 string), and the
   exponent of $nv. (There's an implied radix point between the
   first and second digits of the mantissa).
  #############################################
  @bin = float_H2B($hex);

   As for the above float_B() function - but takes the hex
   string of the NV (as returned by float_H) as its argument,
   instead of the actual NV.
   For a more direct way of obtaining the array, use float_B
   instead.
  #############################################
  $hex = B2float_H(@bin);

   The reverse of float_H2B. It takes the array returned by
   either float_B or float_H2B as its arguments, and returns
   the corresponding hex form.
  #############################################
  ($sign1, $sign2) = get_sign($nv);

   Returns the signs of the two doubles contained in $nv.
  #############################################
  ($exp1, $exp2) = get_exp($nv);

   Returns the exponents of the two doubles contained in $nv.
  #############################################
  ($mantissa1, $mantissa2) = get_mant_H(NV2H($nv));

   Returns an array of the two 52-bit mantissa components of
   the two doubles in their hex form. The values of the
   implied leading (most significant) bits are not provided,
   nor are the values of the two exponents. 
  #############################################
  $intermediate_zeroes = inter_zero(get_exp($nv));

   Returns the number of zeroes that need to come between the
   mantissas of the 2 doubles when $nv is translated to the
   representation that float_H() returns.
  #############################################
  $bool = are_inf(@nv); # Aliased to float_is_infinite.

   Returns true if and only if all of the (NV) arguments are
   infinities.
   Else returns false.
  #############################################
  $bool = are_nan(@nv); # Aliased to float_is_nan.

   Returns true if and only if all of the (NV) arguments are
   NaNs. Else returns false.
  #############################################
  $hex = valid_unpack($string [,$die]); # 2nd arg optional

   Verify that the 1st arg is a valid 'unpack' format - such as
   retured by NV2H.
   Die if it's an empty string.
   Die if it has a length greater than 32.
   Check that it consists only of valid hex characters and that
   there are 32 of them.
   If it consists solely of hex characters but there's less than
   32 of them, either die (if $die is set) or append zeroes until
   the length is 32 (if $die is not set).
   If the string was modified, return that modified string - else
   return the 1st arg. 
  #############################################
  @bin = valid_bin($sign, $mantissa, $exponent [,$die]);

   Checks and returns a validated binary format (sign,
   mantissa, exponent) - such as that returned by float_B().
   Dies if it can't validate the supplied arguments.
   If exponent is 1024, the sub will die unless mantissa matches
   the format for an inf or a nan.
   Dies if exponent > 1024.
   Returns 0 if exponent <= -1075 (unless $die is set &&
   mantissa =~ /1/ - in which case it dies.)
   Unless $die is set, it will make some simple modifications
   if needed:
    1) Set $sign to '+' if it's the empty string;
    2) Append zeroes to $mantissa if there are too few
       characters.
   Return $sign, $mantissa, $exponent.
  #############################################
  $hex = valid_hex($float_string [,$die]);

   Checks and returns a validated hex format - such as that
   returned by float_H. Dies if it can't validate the supplied
   argument.
   Unless $die is set, it will make some simple modifications
   if needed:
    1) Prepend a '+' sign if no sign is present;
    2) Append zeroes if there are too few characters.
   If the string was modified, return that modified string - else
   return the 1st arg.
  #############################################

  For Compatibility with Data::Float:

  #############################################
  $class = float_class($nv);

   Returns one of either "NAN", "INFINITE", "ZERO", "NORMAL"
   or "SUBNORMAL" - whichever is appropriate. (The NV must
   belong to one (and only one) class.
  #############################################
  $bool = float_is_nan($nv); # Alias for are_nan()

   Returns true if $nv is a NaN.
   Else returns false. 
  #############################################
  $bool = float_is_infinite($nv); # Alias for are_inf()

   Returns true if $nv is infinite.
   Else returns false.
  #############################################
  $bool = float_is_finite($nv);

   Returns true if NV is neither infinite nor a NaN.
   Else returns false.
  #############################################
  $bool = float_is_nzfinite($nv);

   Returns true if NV is neither infinite, nor a NaN, nor zero.
   Else returns false.
  #############################################
  $bool = float_is_zero($nv);

   Returns true if NV is zero.
   Else returns false.
  #############################################
  $bool = float_is_normal($nv);

   Returns true if NV is finite && non-zero && the implied
   leading digit in its internal representation is '1'.
   Else returns false.
  #############################################
  $bool = float_is_subnormal($nv);

   Returns true if NV is finite && non-zero && the implied
   leading digit in its internal representation is '0'.
  #############################################
  $nv = nextafter($nv1, $nv2);

   $nv1 and $nv2 must both be floating point values. Returns the
   next representable floating point value adjacent to $nv1 in the
   direction of $nv2, or returns $nv2 if it is numerically
   equal to $nv1. Infinite values are regarded as being adjacent to
   the largest representable finite values. Zero counts as one value,
   even if it is signed, and it is adjacent to the positive and
   negative smallest representable finite values. If a zero is returned
   then it has the same sign as $nv1. Returns
   NaN if either argument is a NaN.
  #############################################
  $nv = nextup($nv1);

   $nv1 must be a floating point value. Returns the next representable
   floating point value adjacent to $nv1 with a numerical value that
   is strictly greater than $nv1, or returns $nv1 unchanged if there
   is no such value. Infinite values are regarded as being adjacent to
   the largest representable finite values. Zero counts as one value,
   even if it is signed, and it is adjacent to the smallest
   representable positive and negative finite values. If a zero is
   returned, because $nv1 is the smallest representable negative
   value, and zeroes are signed, it is a negative zero that is
   returned. Returns NaN if $nv1 is a NaN.
  #############################################
  $nv = nextdown($nv1);

   $nv1 must be a floating point value. Returns the next representable
   floating point value adjacent to $nv1 with a numerical value that
   is strictly less than $nv1, or returns $nv1 unchanged if there is
   no such value. Infinite values are regarded as being adjacent to the
   largest representable finite values. Zero counts as one value, even
   if it is signed, and it is adjacent to the smallest representable
   positive and negative finite values. If a zero is returned, because
   $nv is the smallest representable positive value, and zeroes are
   signed, it is a positive zero that is returned. Returns NaN if VALUE
   is a NaN.
  #############################################
  #############################################

TODO

   Over time, introduce the features of (and functions provided by)
   Data::Float

LICENSE

   This program is free software; you may redistribute it and/or 
   modify it under the same terms as Perl itself.
   Copyright 2014 Sisyphus

AUTHOR

   Sisyphus <sisyphus at(@) cpan dot (.) org>