module Float::Printer::Grisu3
Extended Modules
Defined in:
float/printer/grisu3.crInstance Method Summary
-
#digit_gen(low : DiyFP, w : DiyFP, high : DiyFP, buffer_p) : Tuple(Bool, Int32, Int32)
Generates the digits of input number w.
-
#grisu3(v : Float64 | Float32, buffer_p) : Tuple(Bool, Int32, Int32)
Provides a decimal representation of v.
-
#round_weed(buffer_ptr, length, distance_too_high_w, unsafe_interval, rest, ten_kappa, unit)
Adjusts the last digit of the generated number, and screens out generated solutions that may be inaccurate.
Instance Method Detail
Generates the digits of input number w.
w is a floating-point number (DiyFp), consisting of a significand and an
exponent. Its exponent is bounded by kMinimalTargetExponent and
kMaximalTargetExponent. Hence:
-60 <= w.e() <= -32
Returns false if it fails, in which case the generated digits in the buffer
should not be used.
Preconditions:
- low, w and high are correct up to 1 ulp (unit in the last place). That is, their error must be less than a unit of their last digits.
low.e() == w.e() == high.e()low < w < high, and taking into account their error:low~ <= high~kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
Postconditions: returns false if procedure fails, otherwise:
- buffer is not null-terminated, but len contains the number of digits.
- buffer contains the shortest possible decimal digit-sequence
such that
LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the correct values of low and high (without their error). - if more than one decimal representation gives the minimal number of decimal digits then the one closest to W (where W is the correct value of w) is chosen.
NOTE This procedure takes into account the imprecision of its input
numbers. If the precision is not enough to guarantee all the postconditions
then false is returned. This usually happens rarely (~0.5%).
Say, for the sake of example, that:
w.e() == -48 && w.f() == 0x1234567890abcdef
w's value can be computed by w.f() * 2^w.e()
We can obtain w's integral digits by simply shifting w.f() by -w.e().
- -> w's integral part is
0x1234 - w's fractional part is therefore
0x567890abcdef.
Printing w's integral part is easy (simply print 0x1234 in decimal).
In order to print its fraction we repeatedly multiply the fraction by 10 and
get each digit. Example the first digit after the point would be computed by
(0x567890abcdef * 10) >> 48. -> 3
The whole thing becomes slightly more complicated because we want to stop once we have enough digits. That is, once the digits inside the buffer represent 'w' we can stop. Everything inside the interval low - high represents w. However we have to pay attention to low, high and w's imprecision.
Provides a decimal representation of v.
Returns a Tuple of {status, decimal_exponent, length}
status will be true if it succeeds, otherwise the result cannot be
trusted.
There will be length digits inside the buffer (not null-terminated).
If the function returns status as true then
v == (buffer * 10^decimal_exponent).to_f
The digits in the buffer are the shortest representation possible:
no 0.09999999999999999 instead of 0.1. The shorter representation will
even be chosen even if the longer one would be closer to v.
The last digit will be closest to the actual v. That is, even if several digits might correctly yield v when read again, the closest will be computed.
Adjusts the last digit of the generated number, and screens out generated solutions that may be inaccurate. A solution may be inaccurate if it is outside the safe interval, or if we cannot prove that it is closer to the input than a neighboring representation of the same length.
Input:
- buffer_ptr: buffer pointer containing the digits of
too_high / 10^kappa - length: the buffer's length
- distance_too_high_w:
(too_high - w).frac * unit - unsafe_interval:
(too_high - too_low).frac * unit - rest:
(too_high - buffer * 10^kappa).frac * unit - ten_kappa:
10^kappa * unit - unit: the common multiplier
Output: returns true if the buffer is guaranteed to contain the closest
representable number to the input.
Modifies the generated digits in the buffer to approach (round towards) w.