| /* |
| * Floating Point Convert Doubles to Various |
| * |
| * Copyright (c) 2019, 2024 Linaro |
| * |
| * SPDX-License-Identifier: GPL-2.0-or-later |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <math.h> |
| #include <float.h> |
| #include <fenv.h> |
| |
| |
| #include "float_helpers.h" |
| |
| #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
| |
| typedef struct { |
| int flag; |
| char *desc; |
| } float_mapping; |
| |
| float_mapping round_flags[] = { |
| { FE_TONEAREST, "to nearest" }, |
| #ifdef FE_UPWARD |
| { FE_UPWARD, "upwards" }, |
| #endif |
| #ifdef FE_DOWNWARD |
| { FE_DOWNWARD, "downwards" }, |
| #endif |
| #ifdef FE_TOWARDZERO |
| { FE_TOWARDZERO, "to zero" } |
| #endif |
| }; |
| |
| static void print_input(double input) |
| { |
| char *in_fmt = fmt_f64(input); |
| printf("from double: %s\n", in_fmt); |
| free(in_fmt); |
| } |
| |
| static void convert_double_to_single(double input) |
| { |
| float output; |
| char *out_fmt, *flag_fmt; |
| |
| feclearexcept(FE_ALL_EXCEPT); |
| |
| output = input; |
| |
| flag_fmt = fmt_flags(); |
| out_fmt = fmt_f32(output); |
| printf(" to single: %s (%s)\n", out_fmt, flag_fmt); |
| free(out_fmt); |
| free(flag_fmt); |
| } |
| |
| #define xstr(a) str(a) |
| #define str(a) #a |
| |
| #define CONVERT_DOUBLE_TO_INT(TYPE, FMT) \ |
| static void convert_double_to_ ## TYPE(double input) \ |
| { \ |
| TYPE ## _t output; \ |
| char *flag_fmt; \ |
| const char to[] = "to " xstr(TYPE); \ |
| feclearexcept(FE_ALL_EXCEPT); \ |
| output = input; \ |
| flag_fmt = fmt_flags(); \ |
| printf("%11s: %" FMT " (%s)\n", to, output, flag_fmt); \ |
| free(flag_fmt); \ |
| } |
| |
| CONVERT_DOUBLE_TO_INT( int32, PRId32) |
| CONVERT_DOUBLE_TO_INT(uint32, PRId32) |
| CONVERT_DOUBLE_TO_INT( int64, PRId64) |
| CONVERT_DOUBLE_TO_INT(uint64, PRId64) |
| |
| int main(int argc, char *argv[argc]) |
| { |
| int i, j, nums; |
| |
| nums = get_num_f64(); |
| |
| for (i = 0; i < ARRAY_SIZE(round_flags); ++i) { |
| if (fesetround(round_flags[i].flag) != 0) { |
| printf("### Rounding %s skipped\n", round_flags[i].desc); |
| continue; |
| } |
| printf("### Rounding %s\n", round_flags[i].desc); |
| for (j = 0; j < nums; j++) { |
| double input = get_f64(j); |
| print_input(input); |
| convert_double_to_single(input); |
| convert_double_to_int32(input); |
| convert_double_to_int64(input); |
| convert_double_to_uint32(input); |
| convert_double_to_uint64(input); |
| } |
| } |
| |
| return 0; |
| } |