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