coreutils
coreutils copied to clipboard
od: doesn't support output format specifier "fL"
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
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?
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.
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...
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.
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.