1b059a62bSAlex Bennée /*
2b059a62bSAlex Bennée * Floating Point Convert Single to Various
3b059a62bSAlex Bennée *
4*542b10bdSAlex Bennée * Copyright (c) 2019, 2024 Linaro
5b059a62bSAlex Bennée *
6*542b10bdSAlex Bennée * SPDX-License-Identifier: GPL-2.0-or-later
7b059a62bSAlex Bennée */
8b059a62bSAlex Bennée
9b059a62bSAlex Bennée #include <stdio.h>
10b059a62bSAlex Bennée #include <stdlib.h>
11b059a62bSAlex Bennée #include <math.h>
12b059a62bSAlex Bennée #include <float.h>
13b059a62bSAlex Bennée #include <fenv.h>
14b059a62bSAlex Bennée
15b059a62bSAlex Bennée
16b059a62bSAlex Bennée #include "float_helpers.h"
17b059a62bSAlex Bennée
18b059a62bSAlex Bennée #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
19b059a62bSAlex Bennée
20b059a62bSAlex Bennée typedef struct {
21b059a62bSAlex Bennée int flag;
22b059a62bSAlex Bennée char *desc;
23b059a62bSAlex Bennée } float_mapping;
24b059a62bSAlex Bennée
25b059a62bSAlex Bennée float_mapping round_flags[] = {
26b059a62bSAlex Bennée { FE_TONEAREST, "to nearest" },
27b059a62bSAlex Bennée #ifdef FE_UPWARD
28b059a62bSAlex Bennée { FE_UPWARD, "upwards" },
29b059a62bSAlex Bennée #endif
30b059a62bSAlex Bennée #ifdef FE_DOWNWARD
31b059a62bSAlex Bennée { FE_DOWNWARD, "downwards" },
32b059a62bSAlex Bennée #endif
334c71dc37SRichard Henderson #ifdef FE_TOWARDZERO
34b059a62bSAlex Bennée { FE_TOWARDZERO, "to zero" }
354c71dc37SRichard Henderson #endif
36b059a62bSAlex Bennée };
37b059a62bSAlex Bennée
print_input(float input)38b059a62bSAlex Bennée static void print_input(float input)
39b059a62bSAlex Bennée {
40b059a62bSAlex Bennée char *in_fmt = fmt_f32(input);
41b059a62bSAlex Bennée printf("from single: %s\n", in_fmt);
42b059a62bSAlex Bennée free(in_fmt);
43b059a62bSAlex Bennée }
44b059a62bSAlex Bennée
convert_single_to_double(float input)45b059a62bSAlex Bennée static void convert_single_to_double(float input)
46b059a62bSAlex Bennée {
47b059a62bSAlex Bennée double output;
48b059a62bSAlex Bennée char *out_fmt, *flag_fmt;
49b059a62bSAlex Bennée
50b059a62bSAlex Bennée feclearexcept(FE_ALL_EXCEPT);
51b059a62bSAlex Bennée
52b059a62bSAlex Bennée output = input;
53b059a62bSAlex Bennée
54b059a62bSAlex Bennée flag_fmt = fmt_flags();
55603bd9c2SRichard Henderson out_fmt = fmt_f64(output);
56b059a62bSAlex Bennée printf(" to double: %s (%s)\n", out_fmt, flag_fmt);
57b059a62bSAlex Bennée free(out_fmt);
58b059a62bSAlex Bennée free(flag_fmt);
59b059a62bSAlex Bennée }
60b059a62bSAlex Bennée
61b059a62bSAlex Bennée #define xstr(a) str(a)
62b059a62bSAlex Bennée #define str(a) #a
63b059a62bSAlex Bennée
64b059a62bSAlex Bennée #define CONVERT_SINGLE_TO_INT(TYPE, FMT) \
65b059a62bSAlex Bennée static void convert_single_to_ ## TYPE(float input) \
66b059a62bSAlex Bennée { \
67b059a62bSAlex Bennée TYPE ## _t output; \
68b059a62bSAlex Bennée char *flag_fmt; \
69b059a62bSAlex Bennée const char to[] = "to " xstr(TYPE); \
70b059a62bSAlex Bennée feclearexcept(FE_ALL_EXCEPT); \
71b059a62bSAlex Bennée output = input; \
72b059a62bSAlex Bennée flag_fmt = fmt_flags(); \
73b059a62bSAlex Bennée printf("%11s: %" FMT " (%s)\n", to, output, flag_fmt); \
74b059a62bSAlex Bennée free(flag_fmt); \
75b059a62bSAlex Bennée }
76b059a62bSAlex Bennée
CONVERT_SINGLE_TO_INT(int32,PRId32)77b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT( int32, PRId32)
78b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT(uint32, PRId32)
79b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT( int64, PRId64)
80b059a62bSAlex Bennée CONVERT_SINGLE_TO_INT(uint64, PRId64)
81b059a62bSAlex Bennée
82b059a62bSAlex Bennée int main(int argc, char *argv[argc])
83b059a62bSAlex Bennée {
84b059a62bSAlex Bennée int i, j, nums;
85b059a62bSAlex Bennée
86b059a62bSAlex Bennée nums = get_num_f32();
87b059a62bSAlex Bennée
88b059a62bSAlex Bennée for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
89b059a62bSAlex Bennée if (fesetround(round_flags[i].flag) != 0) {
90b059a62bSAlex Bennée printf("### Rounding %s skipped\n", round_flags[i].desc);
91b059a62bSAlex Bennée continue;
92b059a62bSAlex Bennée }
93b059a62bSAlex Bennée printf("### Rounding %s\n", round_flags[i].desc);
94b059a62bSAlex Bennée for (j = 0; j < nums; j++) {
95b059a62bSAlex Bennée float input = get_f32(j);
96b059a62bSAlex Bennée print_input(input);
97b059a62bSAlex Bennée /* convert_single_to_half(input); */
98b059a62bSAlex Bennée convert_single_to_double(input);
99b059a62bSAlex Bennée convert_single_to_int32(input);
100b059a62bSAlex Bennée convert_single_to_int64(input);
101b059a62bSAlex Bennée convert_single_to_uint32(input);
102b059a62bSAlex Bennée convert_single_to_uint64(input);
103b059a62bSAlex Bennée }
104b059a62bSAlex Bennée }
105b059a62bSAlex Bennée
106b059a62bSAlex Bennée return 0;
107b059a62bSAlex Bennée }
108