//===-- lib/Evaluate/int-power.h --------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef FORTRAN_EVALUATE_INT_POWER_H_ #define FORTRAN_EVALUATE_INT_POWER_H_ // Computes an integer power of a real or complex value. #include "flang/Evaluate/common.h" namespace Fortran::evaluate { template ValueWithRealFlags TimesIntPowerOf(const REAL &factor, const REAL &base, const INT &power, Rounding rounding = defaultRounding) { ValueWithRealFlags result{factor}; if (base.IsNotANumber()) { result.value = REAL::NotANumber(); result.flags.set(RealFlag::InvalidArgument); } else if (power.IsZero()) { if (base.IsZero() || base.IsInfinite()) { result.flags.set(RealFlag::InvalidArgument); } } else { bool negativePower{power.IsNegative()}; INT absPower{power.ABS().value}; REAL squares{base}; int nbits{INT::bits - absPower.LEADZ()}; for (int j{0}; j < nbits; ++j) { if (absPower.BTEST(j)) { if (negativePower) { result.value = result.value.Divide(squares, rounding) .AccumulateFlags(result.flags); } else { result.value = result.value.Multiply(squares, rounding) .AccumulateFlags(result.flags); } } squares = squares.Multiply(squares, rounding).AccumulateFlags(result.flags); } } return result; } template ValueWithRealFlags IntPower( const REAL &base, const INT &power, Rounding rounding = defaultRounding) { REAL one{REAL::FromInteger(INT{1}).value}; return TimesIntPowerOf(one, base, power, rounding); } } // namespace Fortran::evaluate #endif // FORTRAN_EVALUATE_INT_POWER_H_