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