xref: /qemu/tests/tcg/multiarch/float_convd.c (revision b2a3cbb8)
1 /*
2  * Floating Point Convert Doubles 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 #ifdef FE_TOWARDZERO
34     { FE_TOWARDZERO, "to zero" }
35 #endif
36 };
37 
38 static void print_input(double input)
39 {
40     char *in_fmt = fmt_f64(input);
41     printf("from double: %s\n", in_fmt);
42     free(in_fmt);
43 }
44 
45 static void convert_double_to_single(double input)
46 {
47     float output;
48     char *out_fmt, *flag_fmt;
49 
50     feclearexcept(FE_ALL_EXCEPT);
51 
52     output = input;
53 
54     flag_fmt = fmt_flags();
55     out_fmt = fmt_f32(output);
56     printf("  to single: %s (%s)\n", out_fmt, flag_fmt);
57     free(out_fmt);
58     free(flag_fmt);
59 }
60 
61 #define xstr(a) str(a)
62 #define str(a) #a
63 
64 #define CONVERT_DOUBLE_TO_INT(TYPE, FMT)                            \
65     static void convert_double_to_ ## TYPE(double input)            \
66     {                                                               \
67         TYPE ## _t output;                                          \
68         char *flag_fmt;                                             \
69         const char to[] = "to " xstr(TYPE);                         \
70         feclearexcept(FE_ALL_EXCEPT);                               \
71         output = input;                                             \
72         flag_fmt = fmt_flags();                                     \
73         printf("%11s: %" FMT " (%s)\n", to, output, flag_fmt);      \
74         free(flag_fmt);                                             \
75     }
76 
77 CONVERT_DOUBLE_TO_INT( int32, PRId32)
78 CONVERT_DOUBLE_TO_INT(uint32, PRId32)
79 CONVERT_DOUBLE_TO_INT( int64, PRId64)
80 CONVERT_DOUBLE_TO_INT(uint64, PRId64)
81 
82 int main(int argc, char *argv[argc])
83 {
84     int i, j, nums;
85 
86     nums = get_num_f64();
87 
88     for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
89         if (fesetround(round_flags[i].flag) != 0) {
90             printf("### Rounding %s skipped\n", round_flags[i].desc);
91             continue;
92         }
93         printf("### Rounding %s\n", round_flags[i].desc);
94         for (j = 0; j < nums; j++) {
95             double input = get_f64(j);
96             print_input(input);
97             convert_double_to_single(input);
98             convert_double_to_int32(input);
99             convert_double_to_int64(input);
100             convert_double_to_uint32(input);
101             convert_double_to_uint64(input);
102         }
103     }
104 
105     return 0;
106 }
107