xref: /openbmc/qemu/tests/tcg/multiarch/float_convd.c (revision d316f1b14615854de1bf4c0a9789e9c8951cc437)
12931014cSAlex Bennée /*
22931014cSAlex Bennée  * Floating Point Convert Doubles to Various
32931014cSAlex Bennée  *
4*542b10bdSAlex Bennée  * Copyright (c) 2019, 2024 Linaro
52931014cSAlex Bennée  *
6*542b10bdSAlex Bennée  * SPDX-License-Identifier: GPL-2.0-or-later
72931014cSAlex Bennée  */
82931014cSAlex Bennée 
92931014cSAlex Bennée #include <stdio.h>
102931014cSAlex Bennée #include <stdlib.h>
112931014cSAlex Bennée #include <math.h>
122931014cSAlex Bennée #include <float.h>
132931014cSAlex Bennée #include <fenv.h>
142931014cSAlex Bennée 
152931014cSAlex Bennée 
162931014cSAlex Bennée #include "float_helpers.h"
172931014cSAlex Bennée 
182931014cSAlex Bennée #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
192931014cSAlex Bennée 
202931014cSAlex Bennée typedef struct {
212931014cSAlex Bennée     int flag;
222931014cSAlex Bennée     char *desc;
232931014cSAlex Bennée } float_mapping;
242931014cSAlex Bennée 
252931014cSAlex Bennée float_mapping round_flags[] = {
262931014cSAlex Bennée     { FE_TONEAREST, "to nearest" },
272931014cSAlex Bennée #ifdef FE_UPWARD
282931014cSAlex Bennée     { FE_UPWARD, "upwards" },
292931014cSAlex Bennée #endif
302931014cSAlex Bennée #ifdef FE_DOWNWARD
312931014cSAlex Bennée     { FE_DOWNWARD, "downwards" },
322931014cSAlex Bennée #endif
332931014cSAlex Bennée #ifdef FE_TOWARDZERO
342931014cSAlex Bennée     { FE_TOWARDZERO, "to zero" }
352931014cSAlex Bennée #endif
362931014cSAlex Bennée };
372931014cSAlex Bennée 
print_input(double input)382931014cSAlex Bennée static void print_input(double input)
392931014cSAlex Bennée {
402931014cSAlex Bennée     char *in_fmt = fmt_f64(input);
412931014cSAlex Bennée     printf("from double: %s\n", in_fmt);
422931014cSAlex Bennée     free(in_fmt);
432931014cSAlex Bennée }
442931014cSAlex Bennée 
convert_double_to_single(double input)452931014cSAlex Bennée static void convert_double_to_single(double input)
462931014cSAlex Bennée {
472931014cSAlex Bennée     float output;
482931014cSAlex Bennée     char *out_fmt, *flag_fmt;
492931014cSAlex Bennée 
502931014cSAlex Bennée     feclearexcept(FE_ALL_EXCEPT);
512931014cSAlex Bennée 
522931014cSAlex Bennée     output = input;
532931014cSAlex Bennée 
542931014cSAlex Bennée     flag_fmt = fmt_flags();
552931014cSAlex Bennée     out_fmt = fmt_f32(output);
562931014cSAlex Bennée     printf("  to single: %s (%s)\n", out_fmt, flag_fmt);
572931014cSAlex Bennée     free(out_fmt);
582931014cSAlex Bennée     free(flag_fmt);
592931014cSAlex Bennée }
602931014cSAlex Bennée 
612931014cSAlex Bennée #define xstr(a) str(a)
622931014cSAlex Bennée #define str(a) #a
632931014cSAlex Bennée 
642931014cSAlex Bennée #define CONVERT_DOUBLE_TO_INT(TYPE, FMT)                            \
652931014cSAlex Bennée     static void convert_double_to_ ## TYPE(double input)            \
662931014cSAlex Bennée     {                                                               \
672931014cSAlex Bennée         TYPE ## _t output;                                          \
682931014cSAlex Bennée         char *flag_fmt;                                             \
692931014cSAlex Bennée         const char to[] = "to " xstr(TYPE);                         \
702931014cSAlex Bennée         feclearexcept(FE_ALL_EXCEPT);                               \
712931014cSAlex Bennée         output = input;                                             \
722931014cSAlex Bennée         flag_fmt = fmt_flags();                                     \
732931014cSAlex Bennée         printf("%11s: %" FMT " (%s)\n", to, output, flag_fmt);      \
742931014cSAlex Bennée         free(flag_fmt);                                             \
752931014cSAlex Bennée     }
762931014cSAlex Bennée 
CONVERT_DOUBLE_TO_INT(int32,PRId32)772931014cSAlex Bennée CONVERT_DOUBLE_TO_INT( int32, PRId32)
782931014cSAlex Bennée CONVERT_DOUBLE_TO_INT(uint32, PRId32)
792931014cSAlex Bennée CONVERT_DOUBLE_TO_INT( int64, PRId64)
802931014cSAlex Bennée CONVERT_DOUBLE_TO_INT(uint64, PRId64)
812931014cSAlex Bennée 
822931014cSAlex Bennée int main(int argc, char *argv[argc])
832931014cSAlex Bennée {
842931014cSAlex Bennée     int i, j, nums;
852931014cSAlex Bennée 
862931014cSAlex Bennée     nums = get_num_f64();
872931014cSAlex Bennée 
882931014cSAlex Bennée     for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
892931014cSAlex Bennée         if (fesetround(round_flags[i].flag) != 0) {
902931014cSAlex Bennée             printf("### Rounding %s skipped\n", round_flags[i].desc);
912931014cSAlex Bennée             continue;
922931014cSAlex Bennée         }
932931014cSAlex Bennée         printf("### Rounding %s\n", round_flags[i].desc);
942931014cSAlex Bennée         for (j = 0; j < nums; j++) {
952931014cSAlex Bennée             double input = get_f64(j);
962931014cSAlex Bennée             print_input(input);
972931014cSAlex Bennée             convert_double_to_single(input);
982931014cSAlex Bennée             convert_double_to_int32(input);
992931014cSAlex Bennée             convert_double_to_int64(input);
1002931014cSAlex Bennée             convert_double_to_uint32(input);
1012931014cSAlex Bennée             convert_double_to_uint64(input);
1022931014cSAlex Bennée         }
1032931014cSAlex Bennée     }
1042931014cSAlex Bennée 
1052931014cSAlex Bennée     return 0;
1062931014cSAlex Bennée }
107