1
2
3
4
5
6
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
20typedef struct {
21 int flag;
22 char *desc;
23} float_mapping;
24
25float_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
38static 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
45static 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
77CONVERT_DOUBLE_TO_INT( int32, PRId32)
78CONVERT_DOUBLE_TO_INT(uint32, PRId32)
79CONVERT_DOUBLE_TO_INT( int64, PRId64)
80CONVERT_DOUBLE_TO_INT(uint64, PRId64)
81
82int 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