On 01/02/2024 12:43, Rozenberg, Eyal (Consultant) wrote:
If I try to use the od utility to print half-precision (FP16) floating-point values, I get:$ od -t f2 myfloats.bin od: invalid type string 'f2'; this system doesn't provide a 2-byte floating point type I'm not exactly sure what "this system" means, but that should work and print out my floats. Eyal PS - This is my first bug-coreutils post, please be gentle.
I just had a read of these: https://gcc.gnu.org/onlinedocs/gcc/Half-Precision.html https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0192r4.html On the face of it it seems that various 16 bit floating point formats have consolidated, and we could add support for _Float16 in od. I see gnulib already enables __STDC_WANT_IEC_60559_TYPES_EXT__ so we should be able to do something like the attached. This is just off the top of my head, and I haven't tested or thought about this much at all. Any testing your could do would be appreciated. thanks, Pádraig
commit 82fc25ab7f34a8198a8f435c1396801d30e8c6b6 Author: Pádraig Brady <p...@draigbrady.com> Date: Thu Feb 1 17:59:51 2024 +0000 od: support half precision floating point * src/od.c: Suport -t f2 to print 16 bit floating point. * NEWS: Mention the new feature. Addresses https://bugs.gnu.org/68871 diff --git a/src/od.c b/src/od.c index 75bed5e7d..2f03a729e 100644 --- a/src/od.c +++ b/src/od.c @@ -19,6 +19,7 @@ #include <config.h> #include <ctype.h> +#include <float.h> #include <stdio.h> #include <getopt.h> #include <sys/types.h> @@ -49,6 +50,12 @@ typedef unsigned long long int unsigned_long_long_int; typedef unsigned long int unsigned_long_long_int; #endif +#ifndef FLT16_MAX +/* This is just a place-holder to avoid a few '#if' directives. + In this case, the type isn't actually used. */ +typedef float _Float16; +#endif + enum size_spec { NO_SIZE, @@ -58,6 +65,7 @@ enum size_spec LONG, LONG_LONG, /* FIXME: add INTMAX support, too */ + FLOAT_HALF, FLOAT_SINGLE, FLOAT_DOUBLE, FLOAT_LONG_DOUBLE, @@ -156,6 +164,7 @@ static const int width_bytes[] = sizeof (int), sizeof (long int), sizeof (unsigned_long_long_int), + sizeof (_Float16), sizeof (float), sizeof (double), sizeof (long double) @@ -477,6 +486,7 @@ PRINT_TYPE (print_int, unsigned int) PRINT_TYPE (print_long, unsigned long int) PRINT_TYPE (print_long_long, unsigned_long_long_int) +PRINT_FLOATTYPE (print_halffloat, _Float16, ftoastr, FLT_BUFSIZE_BOUND) PRINT_FLOATTYPE (print_float, float, ftoastr, FLT_BUFSIZE_BOUND) PRINT_FLOATTYPE (print_double, double, dtoastr, DBL_BUFSIZE_BOUND) PRINT_FLOATTYPE (print_long_double, long double, ldtoastr, LDBL_BUFSIZE_BOUND) @@ -824,6 +834,11 @@ decode_one_format (char const *s_orig, char const *s, char const **next, switch (size_spec) { + case FLOAT_HALF: + print_function = print_halffloat; + field_width = FLT_STRLEN_BOUND_L (decimal_point_len); + break; + case FLOAT_SINGLE: print_function = print_float; field_width = FLT_STRLEN_BOUND_L (decimal_point_len); @@ -1598,6 +1613,9 @@ main (int argc, char **argv) for (i = 0; i <= MAX_FP_TYPE_SIZE; i++) fp_type_size[i] = NO_SIZE; +#ifdef FLT16_MAX + fp_type_size[sizeof (_Float16)] = FLOAT_HALF; +#endif fp_type_size[sizeof (float)] = FLOAT_SINGLE; /* The array entry for 'double' is filled in after that for 'long double' so that if they are the same size, we avoid any overhead of