Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support floating-point formatting #2

Open
3 of 6 tasks
Viatorus opened this issue Dec 8, 2022 · 2 comments
Open
3 of 6 tasks

Support floating-point formatting #2

Viatorus opened this issue Dec 8, 2022 · 2 comments
Milestone

Comments

@Viatorus
Copy link
Owner

Viatorus commented Dec 8, 2022

  • Check if dragonbox has an acceptable binary size (for single and double precision)
  • If not, find an alternative
  • implement the low-level writer API
  • implement the high-level format API
    • support hexfloat
    • float is upcasted to double (is this a real issue?)
@Viatorus Viatorus added this to the 1.0.0 milestone Dec 9, 2022
@Viatorus
Copy link
Owner Author

Viatorus commented Apr 19, 2023

  • Dragonbox can "only" find the shortest representation but not with arbitrary precision.
  • There exist some other newer algorithm like floff, Ryu or Grisu3. They are all faster than Dragon4.
  • Dragon4 does use way less binary size so I went with this one. But the current implementation requires much stack size (~1 - 1.5 kByte)

@Viatorus
Copy link
Owner Author

Viatorus commented Oct 12, 2023

Some more questions occurred, why I choose Dragon4.

My selection criteria were:

  1. it should be possible to format and scan floating-point values
  2. it should be possible to format the shortest form and the fixed-precision form
  3. it should not take up much binary size
  4. it should be fast

Results for 4., shortest form

dragonbox > (is faster than) ryu > grisu-exact > dragon4

Reference:

Results for 4., fixed-precision form

floff> (is faster than) ryu > grisu2 > dragon4

Reference:

Results for 3., binary code size

  • fmtlib's implementation with Dragonbox and Grisu2 requires 7.5 kB
  • floff's implementation requires 25.8 kB
  • floff's compressed implementation requires 12.5 kB
  • emio's Dragon4 implementation requires 3.7 kB
  • No test result of ryu available anymore but if I remember correctly, it was much huger than floff

Reference:

Results for 2., shortest form and fixed-precision form

  • both forms:
    • Dragon4
    • ryu
  • shortest form:
    • Dragonbox only for
    • Grisu-Exact for shortest form
  • fixed-precision form:
    • Grisu2 for fixed-precision form
    • floff only for fixed-precision form

Conclusion: To offer both forms, I would have to combine different algorithms, which in turn increases the binary size.

Results for 1., format and scan

As far as I am aware of, only with arbitrary integer arithmetic a string can be exactly parsed into a double. Please correct me if a am wrong!

So with Dragon4, which already uses arbitrary integer arithmetic, I can save binary code size. But I also don't know a good algorithm & implementation of the parsing part yet...

Current Winner

Dragon4, because the code reuse decreases the required binary size significant.

The downsides of Dragon4:

The current implementation is based on https://github.com/rust-lang/rust/blob/71ef9ecbdedb67c32f074884f503f8e582855c2f/library/core/src/num/flt2dec/strategy/dragon.rs because it was the cleanest I have found.

it is a slow algorithm

  • shortest form is ~8.5 (gcc), ~10 (clang) times slower than dragonbox (from fmtlib)
  • fixed-precsion form is ~2.5 times slower than Grisu2 (from fmtlib)
  • fixed-precsion form is ~1.5 times slower than printf's Dragon4 implementation

Reference:

requires much stack size

Embedded devices often have less RAM (128 kB - 2 MB). If an RTOS is used, each task stack is a fraction of it.
To avoid heap allocation (not like the printf implementation is doing it), the big integers are allocated on the stack.

One big integer object requires 140 bytes (size_t + 34 * 4 bytes) (32 bit system).

  • emio::detail::format::format_exact requires 0.8 kB of stack
  • emio::detail::format::format_shortest requires 1.2 kB of stack
  • (floff e.g. only requires ~0.2 kB)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant