"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-fp-error.c" (15 Mar 2019, 4513 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-fp-error.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.49_vs_0.09.50.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 #if !defined(__UCLIBC__) && \
   28     defined(HAVE_FENV_H) && \
   29     defined(HAVE_FLOAT_H)
   30 
   31 #define SET_VOLATILE(d, val)    \
   32 do {                \
   33     d = val;        \
   34     (void)&d;       \
   35 } while (0)         \
   36 
   37 
   38 static inline void stress_fp_clear_error(void)
   39 {
   40     errno = 0;
   41     feclearexcept(FE_ALL_EXCEPT);
   42 }
   43 
   44 static inline bool stress_double_same(const double d1, const double d2)
   45 {
   46     if (isnan(d1) && isnan(d2))
   47         return true;
   48     if (isinf(d1) && isinf(d2))
   49         return true;
   50     return (d1 - d2) < 0.0000001;
   51 }
   52 
   53 static void stress_fp_check(
   54     const args_t *args,
   55     const char *expr,
   56     const double val,
   57     const double val_wanted,
   58     const int errno_wanted,
   59     const int excepts_wanted)
   60 {
   61 #if defined(__linux__) && NEED_GNUC(4,8,0)
   62     if (stress_double_same(val, val_wanted) &&
   63         (fetestexcept(excepts_wanted) & excepts_wanted) &&
   64         (errno == errno_wanted))
   65         return;
   66 
   67     pr_fail("%s: %s return was %f (expected %f), "
   68         "errno=%d (expected %d), "
   69         "excepts=%d (expected %d)\n",
   70         args->name, expr,
   71         val, val_wanted,
   72         errno, errno_wanted,
   73         fetestexcept(excepts_wanted), excepts_wanted);
   74 #else
   75     (void)errno_wanted;
   76     (void)excepts_wanted;
   77 
   78     if (stress_double_same(val, val_wanted))
   79         return;
   80 
   81     pr_fail("%s: %s return was %f (expected %f)\n",
   82         args->name, expr,
   83         val, val_wanted);
   84 #endif
   85 }
   86 
   87 /*
   88  *  stress_fp_error()
   89  *  stress floating point error handling
   90  */
   91 static int stress_fp_error(const args_t *args)
   92 {
   93     do {
   94         volatile double d1, d2;
   95 
   96 #if defined(EDOM)
   97         stress_fp_clear_error();
   98         stress_fp_check(args, "log(-1.0)", log(-1.0), NAN,
   99             EDOM, FE_INVALID);
  100 #endif
  101 
  102 #if defined(ERANGE)
  103         stress_fp_clear_error();
  104         stress_fp_check(args, "log(0.0)", log(0.0), -HUGE_VAL,
  105             ERANGE, FE_DIVBYZERO);
  106 #endif
  107 
  108 #if defined(EDOM)
  109         stress_fp_clear_error();
  110         stress_fp_check(args, "log2(-1.0)", log2(-1.0), NAN,
  111             EDOM, FE_INVALID);
  112 #endif
  113 
  114 #if defined(ERANGE)
  115         stress_fp_clear_error();
  116         stress_fp_check(args, "log2(0.0)", log2(0.0), -HUGE_VAL,
  117             ERANGE, FE_DIVBYZERO);
  118 #endif
  119 
  120 #if defined(EDOM)
  121         stress_fp_clear_error();
  122         stress_fp_check(args, "sqrt(-1.0)", sqrt(-1.0), NAN,
  123             EDOM, FE_INVALID);
  124 #endif
  125 
  126 #if defined(EDOM)
  127         stress_fp_clear_error();
  128         stress_fp_check(args, "sqrt(-1.0)", sqrt(-1.0), NAN,
  129             EDOM, FE_INVALID);
  130 #endif
  131 
  132         /*
  133          * Use volatiles to force compiler to generate code
  134          * to perform run time computation of 1.0 / M_PI
  135          */
  136         stress_fp_clear_error();
  137         SET_VOLATILE(d1, 1.0);
  138         SET_VOLATILE(d2, M_PI);
  139         stress_fp_check(args, "1.0 / M_PI", d1 / d2, d1 / d2,
  140             0, FE_INEXACT);
  141 
  142         /*
  143          * Use volatiles to force compiler to generate code
  144          * to perform run time overflow computation
  145          */
  146         stress_fp_clear_error();
  147         SET_VOLATILE(d1, DBL_MAX);
  148         SET_VOLATILE(d2, DBL_MAX / 2.0);
  149         stress_fp_check(args, "DBL_MAX + DBL_MAX / 2.0",
  150             DBL_MAX + DBL_MAX / 2.0, INFINITY,
  151             0, FE_OVERFLOW | FE_INEXACT);
  152 
  153 #if defined(ERANGE)
  154         stress_fp_clear_error();
  155         stress_fp_check(args, "exp(-1000000.0)", exp(-1000000.0), 0.0,
  156             ERANGE, FE_UNDERFLOW);
  157 #endif
  158 
  159 #if defined(ERANGE)
  160         stress_fp_clear_error();
  161         stress_fp_check(args, "exp(DBL_MAX)", exp(DBL_MAX), HUGE_VAL,
  162             ERANGE, FE_OVERFLOW);
  163 #endif
  164 
  165         if (fegetround() == -1)
  166             pr_fail("%s: fegetround() returned -1\n", args->name);
  167         inc_counter(args);
  168     } while (keep_stressing());
  169 
  170     return EXIT_SUCCESS;
  171 }
  172 
  173 stressor_info_t stress_fp_error_info = {
  174     .stressor = stress_fp_error,
  175     .class = CLASS_CPU
  176 };
  177 #else
  178 stressor_info_t stress_fp_error_info = {
  179     .stressor = stress_not_implemented,
  180     .class = CLASS_CPU
  181 };
  182 #endif