164ab3302SCarolineConcatto //===-- lib/Evaluate/int-power.h --------------------------------*- C++ -*-===// 264ab3302SCarolineConcatto // 364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information. 564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 664ab3302SCarolineConcatto // 764ab3302SCarolineConcatto //===----------------------------------------------------------------------===// 864ab3302SCarolineConcatto 964ab3302SCarolineConcatto #ifndef FORTRAN_EVALUATE_INT_POWER_H_ 1064ab3302SCarolineConcatto #define FORTRAN_EVALUATE_INT_POWER_H_ 1164ab3302SCarolineConcatto 1264ab3302SCarolineConcatto // Computes an integer power of a real or complex value. 1364ab3302SCarolineConcatto 1423c2bedfSPeter Klausler #include "flang/Evaluate/target.h" 1564ab3302SCarolineConcatto 1664ab3302SCarolineConcatto namespace Fortran::evaluate { 1764ab3302SCarolineConcatto 1864ab3302SCarolineConcatto template <typename REAL, typename INT> 1964ab3302SCarolineConcatto ValueWithRealFlags<REAL> TimesIntPowerOf(const REAL &factor, const REAL &base, 2023c2bedfSPeter Klausler const INT &power, 2123c2bedfSPeter Klausler Rounding rounding = TargetCharacteristics::defaultRounding) { 2264ab3302SCarolineConcatto ValueWithRealFlags<REAL> result{factor}; 2364ab3302SCarolineConcatto if (base.IsNotANumber()) { 2464ab3302SCarolineConcatto result.value = REAL::NotANumber(); 2564ab3302SCarolineConcatto result.flags.set(RealFlag::InvalidArgument); 2664ab3302SCarolineConcatto } else if (power.IsZero()) { 2764ab3302SCarolineConcatto if (base.IsZero() || base.IsInfinite()) { 2864ab3302SCarolineConcatto result.flags.set(RealFlag::InvalidArgument); 2964ab3302SCarolineConcatto } 3064ab3302SCarolineConcatto } else { 3164ab3302SCarolineConcatto bool negativePower{power.IsNegative()}; 3264ab3302SCarolineConcatto INT absPower{power.ABS().value}; 3364ab3302SCarolineConcatto REAL squares{base}; 3464ab3302SCarolineConcatto int nbits{INT::bits - absPower.LEADZ()}; 3564ab3302SCarolineConcatto for (int j{0}; j < nbits; ++j) { 36*31505c4fSPeter Klausler if (j > 0) { // avoid spurious overflow on last iteration 37*31505c4fSPeter Klausler squares = 38*31505c4fSPeter Klausler squares.Multiply(squares, rounding).AccumulateFlags(result.flags); 39*31505c4fSPeter Klausler } 4064ab3302SCarolineConcatto if (absPower.BTEST(j)) { 4164ab3302SCarolineConcatto if (negativePower) { 4264ab3302SCarolineConcatto result.value = result.value.Divide(squares, rounding) 4364ab3302SCarolineConcatto .AccumulateFlags(result.flags); 4464ab3302SCarolineConcatto } else { 4564ab3302SCarolineConcatto result.value = result.value.Multiply(squares, rounding) 4664ab3302SCarolineConcatto .AccumulateFlags(result.flags); 4764ab3302SCarolineConcatto } 4864ab3302SCarolineConcatto } 4964ab3302SCarolineConcatto } 5064ab3302SCarolineConcatto } 5164ab3302SCarolineConcatto return result; 5264ab3302SCarolineConcatto } 5364ab3302SCarolineConcatto 5464ab3302SCarolineConcatto template <typename REAL, typename INT> 5523c2bedfSPeter Klausler ValueWithRealFlags<REAL> IntPower(const REAL &base, const INT &power, 5623c2bedfSPeter Klausler Rounding rounding = TargetCharacteristics::defaultRounding) { 5764ab3302SCarolineConcatto REAL one{REAL::FromInteger(INT{1}).value}; 5864ab3302SCarolineConcatto return TimesIntPowerOf(one, base, power, rounding); 5964ab3302SCarolineConcatto } 601f879005STim Keith } // namespace Fortran::evaluate 6164ab3302SCarolineConcatto #endif // FORTRAN_EVALUATE_INT_POWER_H_ 62