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