expand_exact Subroutine

private pure subroutine expand_exact(value, exact, n_exact, point_pos)

Exact decimal expansion of a finite, strictly positive value.

An IEEE value is mantissa * 2**pow2 with an integer mantissa. When pow2 is negative that equals mantissa * 5**(-pow2) / 10**(-pow2), so the exact decimal digits are the digits of the big integer mantissa * 5**(-pow2) with the point shifted -pow2 places. When pow2 is positive the value is the integer mantissa * 2**pow2. Either way no rounding whatsoever happens here.

On return the value equals 0.<digits> * 10**point_pos, where <digits> is exact(1:n_exact).

Arguments

Type IntentOptional Attributes Name
real(kind=dp), intent(in) :: value
character(len=*), intent(out) :: exact
integer(kind=default_int), intent(out) :: n_exact
integer(kind=default_int), intent(out) :: point_pos

Calls

proc~~expand_exact~~CallsGraph proc~expand_exact expand_exact proc~bd_mul_pow bd_mul_pow proc~expand_exact->proc~bd_mul_pow proc~bd_set bd_set proc~expand_exact->proc~bd_set proc~bd_to_digits bd_to_digits proc~expand_exact->proc~bd_to_digits proc~bd_mul_small bd_mul_small proc~bd_mul_pow->proc~bd_mul_small proc~limb_to_digits limb_to_digits proc~bd_to_digits->proc~limb_to_digits

Called by

proc~~expand_exact~~CalledByGraph proc~expand_exact expand_exact proc~to_string_fixed_dp to_string_fixed_dp proc~to_string_fixed_dp->proc~expand_exact proc~to_string_sci_dp to_string_sci_dp proc~to_string_sci_dp->proc~expand_exact interface~to_string_fixed to_string_fixed interface~to_string_fixed->proc~to_string_fixed_dp proc~to_string_fixed_sp to_string_fixed_sp interface~to_string_fixed->proc~to_string_fixed_sp interface~to_string_sci to_string_sci interface~to_string_sci->proc~to_string_sci_dp proc~to_string_sci_sp to_string_sci_sp interface~to_string_sci->proc~to_string_sci_sp proc~to_string_fixed_sp->proc~to_string_fixed_dp proc~to_string_sci_sp->proc~to_string_sci_dp

Variables

Type Visibility Attributes Name Initial
integer(kind=int64), private :: limb(MAX_LIMBS)
integer(kind=int64), private :: mantissa
integer(kind=default_int), private :: n_bits
integer(kind=default_int), private :: n_limb
integer(kind=default_int), private :: pow2
integer(kind=default_int), private :: shift

Source Code

   pure subroutine expand_exact(value, exact, n_exact, point_pos)
      !! Exact decimal expansion of a finite, strictly positive value.
      !!
      !! An IEEE value is `mantissa * 2**pow2` with an integer mantissa. When
      !! `pow2` is negative that equals `mantissa * 5**(-pow2) / 10**(-pow2)`,
      !! so the exact decimal digits are the digits of the big integer
      !! `mantissa * 5**(-pow2)` with the point shifted `-pow2` places. When
      !! `pow2` is positive the value is the integer `mantissa * 2**pow2`.
      !! Either way no rounding whatsoever happens here.
      !!
      !! On return the value equals `0.<digits> * 10**point_pos`, where
      !! `<digits>` is `exact(1:n_exact)`.
      real(dp), intent(in) :: value
      character(len=*), intent(out) :: exact
      integer(default_int), intent(out) :: n_exact
      integer(default_int), intent(out) :: point_pos

      integer(int64) :: limb(MAX_LIMBS)
      integer(int64) :: mantissa
      integer(default_int) :: n_limb, n_bits, pow2, shift

      n_bits = int(digits(value), default_int)
      pow2 = int(exponent(value), default_int) - n_bits
      mantissa = int(scale(fraction(value), n_bits), int64)

      call bd_set(limb, n_limb, mantissa)
      shift = 0_default_int
      if (pow2 > 0_default_int) then
         call bd_mul_pow(limb, n_limb, 2_int64, pow2)
      else if (pow2 < 0_default_int) then
         call bd_mul_pow(limb, n_limb, 5_int64, -pow2)
         shift = -pow2
      end if

      call bd_to_digits(limb, n_limb, exact, n_exact)
      point_pos = n_exact - shift

   end subroutine expand_exact