/* Multiply a 'float' by a power of 2. Copyright 2002-2003, 2007-2024 Free Software Foundation, Inc. This file is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ /* Written by Paolo Bonzini and Bruno Haible. */ #include /* Specification. */ #include # include #ifdef USE_LONG_DOUBLE # include "fpucw.h" #endif /* Avoid some warnings from "gcc -Wshadow". This file doesn't use the exp() function. */ #undef exp #define exp exponent #ifdef USE_LONG_DOUBLE # define FUNC ldexpl # define DOUBLE long double # define ISNAN isnanl # define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING # define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING () # define END_ROUNDING() END_LONG_DOUBLE_ROUNDING () # define L_(literal) literal##L #else # define FUNC ldexp # define DOUBLE double # define ISNAN isnand # define DECL_ROUNDING # define BEGIN_ROUNDING() # define END_ROUNDING() # define L_(literal) literal #endif DOUBLE FUNC (DOUBLE x, int exp) { DECL_ROUNDING BEGIN_ROUNDING (); /* Check for zero, nan and infinity. */ if (!(ISNAN (x) || x + x == x)) { DOUBLE factor = exp < 0 ? L_(0.5) : L_(2.0); while (true) { if (exp % 2 != 0) x *= factor; exp /= 2; if (exp == 0) break; factor = factor * factor; } } END_ROUNDING (); return x; }