diff -ru orig/coreutils-9.4/man/od.1 coreutils-9.4/man/od.1 --- orig/coreutils-9.4/man/od.1 2023-08-29 16:57:46.000000000 +0300 +++ coreutils-9.4/man/od.1 2023-09-28 07:06:27.884515095 +0300 @@ -121,7 +121,7 @@ SIZE is a number. For TYPE in [doux], SIZE may also be C for sizeof(char), S for sizeof(short), I for sizeof(int) or L for sizeof(long). If TYPE is f, SIZE may also be F for sizeof(float), D -for sizeof(double) or L for sizeof(long double). +for sizeof(double), L for sizeof(long double) or B for bfloat16. .PP Adding a z suffix to any type displays printable characters at the end of each output line. diff -ru orig/coreutils-9.4/src/od.c coreutils-9.4/src/od.c --- orig/coreutils-9.4/src/od.c 2023-08-29 14:39:27.000000000 +0300 +++ coreutils-9.4/src/od.c 2023-09-28 07:17:47.152408661 +0300 @@ -22,6 +22,7 @@ #include #include #include +#include #include "system.h" #include "argmatch.h" #include "assure.h" @@ -58,6 +59,8 @@ LONG, LONG_LONG, /* FIXME: add INTMAX support, too */ + FLOAT_BRAIN, + FLOAT_HALF, FLOAT_SINGLE, FLOAT_DOUBLE, FLOAT_LONG_DOUBLE, @@ -156,6 +159,8 @@ sizeof (int), sizeof (long int), sizeof (unsigned_long_long_int), + 2, + 2, sizeof (float), sizeof (double), sizeof (long double) @@ -401,7 +406,7 @@ SIZE is a number. For TYPE in [doux], SIZE may also be C for\n\ sizeof(char), S for sizeof(short), I for sizeof(int) or L for\n\ sizeof(long). If TYPE is f, SIZE may also be F for sizeof(float), D\n\ -for sizeof(double) or L for sizeof(long double).\n\ +for sizeof(double), L for sizeof(long double) or B for bfloat16.\n\ "), stdout); fputs (_("\ \n\ @@ -427,6 +432,42 @@ /* Define the print functions. */ +static float +half_to_float (unsigned int x) +{ + union { + float f; + unsigned int i; + } u; + if (!x) + return 0.0; + if (x == 0x8000) + return -0.0; + if ((x & 0x7C00) == 0x7C00) { + u.i = + (x & 0x8000) << 16 + | 0x7F800000 + | (x & 0x03FF) << 13; + } else { + u.i = + (x & 0x8000) << 16 + | (((x & 0x7C00) >> 10) + 127 - 15) << 23 + | (x & 0x03FF) << 13; + } + return u.f; +} + +static float +brain_to_float (unsigned int x) +{ + union { + float f; + unsigned int i; + } u; + u.i = x << 16; + return u.f; +} + #define PRINT_FIELDS(N, T, FMT_STRING_DECL, ACTION) \ static void \ N (size_t fields, size_t blank, void const *block, \ @@ -469,6 +510,20 @@ FTOASTR (buf, sizeof buf, 0, 0, x); \ xprintf ("%*s", adjusted_width, buf)) +#define PRINT_FLOATTYPE_HALF(N, T, FTOASTR, BUFSIZE) \ + PRINT_FIELDS (N, T, MAYBE_UNUSED char const *fmt_string, \ + char buf[BUFSIZE]; \ + float z = half_to_float (x); \ + FTOASTR (buf, sizeof buf, 0, 0, z); \ + xprintf ("%*s", adjusted_width, buf)) + +#define PRINT_FLOATTYPE_BRAIN(N, T, FTOASTR, BUFSIZE) \ + PRINT_FIELDS (N, T, MAYBE_UNUSED char const *fmt_string, \ + char buf[BUFSIZE]; \ + float z = brain_to_float (x); \ + FTOASTR (buf, sizeof buf, 0, 0, z); \ + xprintf ("%*s", adjusted_width, buf)) + PRINT_TYPE (print_s_char, signed char) PRINT_TYPE (print_char, unsigned char) PRINT_TYPE (print_s_short, short int) @@ -477,12 +532,16 @@ PRINT_TYPE (print_long, unsigned long int) PRINT_TYPE (print_long_long, unsigned_long_long_int) +PRINT_FLOATTYPE_BRAIN (print_brain, unsigned short int, ftoastr, FLT_BUFSIZE_BOUND) +PRINT_FLOATTYPE_HALF (print_half, unsigned short int, 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) #undef PRINT_TYPE #undef PRINT_FLOATTYPE +#undef PRINT_FLOATTYPE_HALF +#undef PRINT_FLOATTYPE_BRAIN static void dump_hexl_mode_trailer (size_t n_bytes, char const *block) @@ -770,9 +829,20 @@ case 'f': fmt = FLOATING_POINT; + size_spec = NO_SIZE; ++s; switch (*s) { + case 'S': + ++s; + size = sizeof (short); + break; + + case 'B': /* bfloat16 */ + ++s; + size_spec = FLOAT_BRAIN; + break; + case 'F': ++s; size = sizeof (float); @@ -815,7 +885,8 @@ } break; } - size_spec = fp_type_size[size]; + if (size_spec == NO_SIZE) + size_spec = fp_type_size[size]; { struct lconv const *locale = localeconv (); @@ -824,6 +895,16 @@ switch (size_spec) { + case FLOAT_BRAIN: + print_function = print_brain; + field_width = FLT_STRLEN_BOUND_L (decimal_point_len); + break; + + case FLOAT_HALF: + print_function = print_half; + 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 +1679,7 @@ for (i = 0; i <= MAX_FP_TYPE_SIZE; i++) fp_type_size[i] = NO_SIZE; + fp_type_size[2] = FLOAT_HALF; 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