qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

float_madds.c (2225B)


      1 /*
      2  * Fused Multiply Add (Single)
      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 #include "float_helpers.h"
     16 
     17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
     18 
     19 typedef struct {
     20     int flag;
     21     char *desc;
     22 } float_mapping;
     23 
     24 float_mapping round_flags[] = {
     25     { FE_TONEAREST, "to nearest" },
     26 #ifdef FE_UPWARD
     27     { FE_UPWARD, "upwards" },
     28 #endif
     29 #ifdef FE_DOWNWARD
     30     { FE_DOWNWARD, "downwards" },
     31 #endif
     32 #ifdef FE_TOWARDZERO
     33     { FE_TOWARDZERO, "to zero" }
     34 #endif
     35 };
     36 
     37 
     38 static void print_inputs(float a, float b, float c)
     39 {
     40     char *a_fmt, *b_fmt, *c_fmt;
     41 
     42     a_fmt = fmt_f32(a);
     43     b_fmt = fmt_f32(b);
     44     c_fmt = fmt_f32(c);
     45 
     46     printf("op : %s * %s + %s\n", a_fmt, b_fmt, c_fmt);
     47 
     48     free(a_fmt);
     49     free(b_fmt);
     50     free(c_fmt);
     51 }
     52 
     53 static void print_result(float r, int j, int k)
     54 {
     55     char *r_fmt, *flag_fmt;
     56 
     57     flag_fmt = fmt_flags();
     58     r_fmt = fmt_f32(r);
     59 
     60     printf("res: %s flags=%s (%d/%d)\n", r_fmt, flag_fmt, j, k);
     61 
     62     free(r_fmt);
     63     free(flag_fmt);
     64 }
     65 
     66 static void do_madds(float a, float b, float c, int j, int k)
     67 {
     68     float r;
     69 
     70     print_inputs(a, b, c);
     71 
     72     feclearexcept(FE_ALL_EXCEPT);
     73     r = __builtin_fmaf(a, b, c);
     74 
     75     print_result(r, j, k);
     76 }
     77 
     78 int main(int argc, char *argv[argc])
     79 {
     80     int i, j, k, nums = get_num_f32();
     81     float a, b, c;
     82 
     83     for (i = 0; i < ARRAY_SIZE(round_flags); ++i) {
     84         if (fesetround(round_flags[i].flag) != 0) {
     85             printf("### Rounding %s skipped\n", round_flags[i].desc);
     86             continue;
     87         }
     88         printf("### Rounding %s\n", round_flags[i].desc);
     89         for (j = 0; j < nums; j++) {
     90             for (k = 0; k < 3; k++) {
     91                 a = get_f32(j + ((k)%3));
     92                 b = get_f32(j + ((k+1)%3));
     93                 c = get_f32(j + ((k+2)%3));
     94                 do_madds(a, b, c, j, k);
     95             }
     96         }
     97 
     98         /* From https://bugs.launchpad.net/qemu/+bug/1841491 */
     99         printf("# LP184149\n");
    100         do_madds(0x1.ffffffffffffcp-1022, 0x1.0000000000001p-1, 0x0.0000000000001p-1022, j, 0);
    101         do_madds(0x8p-152, 0x8p-152, 0x8p-152, j+1, 0);
    102     }
    103 
    104     return 0;
    105 }