qemu/tests/tcg/multiarch/float_convd.c
<<
>>
Prefs
   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
  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