coreutils icon indicating copy to clipboard operation
coreutils copied to clipboard

od: doesn't support output format specifier "fL"

Open jfinkels opened this issue 3 years ago • 5 comments

The uutils version of od does not support the fL output format specifier. It means "format the output as a floating point number, using sizeof(long double) bytes to interpret each number in the input". For more information, see: https://www.gnu.org/software/coreutils/manual/html_node/od-invocation.html

GNU od:

$ : | od -tfL
0000000

uutils od:

$ : | ./target/debug/od -tfL
./target/debug/od: unexpected char 'L' in format specification 'fL'

Here's the relevant part of the code: https://github.com/uutils/coreutils/blob/b14e396983c70f816e88e0c8279f91cade809af4/src/uu/od/src/parse_formats.rs#L233

jfinkels avatar Feb 08 '22 02:02 jfinkels

Is there a reason this hasn't been touched in a while? Does the difficulty lie in supporting 128 bit floats, which are not in the Rust standard library? Would we have to use an external crate to support them?

fritzrehde avatar Sep 04 '23 14:09 fritzrehde

I suspect that's indeed the reason. We already have an external library for f16 (half), so another one for f128 makes sense to me. An RFC for both types is being worked on, but might take a while to land.

tertsdiepraam avatar Sep 04 '23 15:09 tertsdiepraam

See here for the RFC: https://github.com/rust-lang/rfcs/pull/3453.

It mentions the f128 crate which seems to be GCC only if I understand correctly? Maybe this just needs to be delayed until that RFC comes through then...

tertsdiepraam avatar Sep 04 '23 15:09 tertsdiepraam

I looked around a little as well, and many promising crates like rug are just wrappers around some GNU libraries. I'm not sure if using such crates go against the philosophy of this project, since they're not pure-rust. Furthermore, I read that installing rug on windows is not straightforward, and I'm guessing this project supports windows. I would also agree that waiting for official Rust std lib support sounds like the best option for now.

fritzrehde avatar Sep 04 '23 15:09 fritzrehde

od -t fL uses whatever long double is on a given platform, that is 80-bit on x86(-64).

Taking some of the examples from Wikipedia:

$ printf $(printf "0000 0000 0000 0000 0001" | tr -d ' ' | sed -e 's/\(..\)/\\x\1\n/g' | tac | tr -d '\n') | od -t fL
0000000                       4e-4951
0000012
$ printf $(printf "4000 8000 0000 0000 0000" | tr -d ' ' | sed -e 's/\(..\)/\\x\1\n/g' | tac | tr -d '\n') | od -t fL
0000000                             2
0000012
$ printf $(printf "3ffd aaaa aaaa aaaa aaab" | tr -d ' ' | sed -e 's/\(..\)/\\x\1\n/g' | tac | tr -d '\n') | od -t fL
0000000        0.33333333333333333334
0000012

Rust support for f128 support would help a bit, as an f80 would hopefully be able to fit exactly in an f128, but we can also use an ExtendedBigDecimal to store the number.


Also note that the top 48 bits of each value are ignored (so the f80s are padded to 128 bits):

printf $(printf "cafe cafe cafe 0000 0000 0000 0000 0001" | tr -d ' ' | sed -e 's/\(..\)/\\x\1\n/g' | tac | tr -d '\n') | od -t fL
0000000                       4e-4951

I'll start implementing a f80 parser to start with (and ExtendedBigDecimal formatter), we can decide later what to do with with non-x86 architectures.

drinkcat avatar Jul 31 '25 12:07 drinkcat