brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.1 KiB · 2ee012c Raw
62 lines · c
1//===-- lib/Evaluate/int-power.h --------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef FORTRAN_EVALUATE_INT_POWER_H_10#define FORTRAN_EVALUATE_INT_POWER_H_11 12// Computes an integer power of a real or complex value.13 14#include "flang/Evaluate/target.h"15 16namespace Fortran::evaluate {17 18template <typename REAL, typename INT>19ValueWithRealFlags<REAL> TimesIntPowerOf(const REAL &factor, const REAL &base,20    const INT &power,21    Rounding rounding = TargetCharacteristics::defaultRounding) {22  ValueWithRealFlags<REAL> result{factor};23  if (base.IsNotANumber()) {24    result.value = REAL::NotANumber();25    result.flags.set(RealFlag::InvalidArgument);26  } else if (power.IsZero()) {27    if (base.IsZero() || base.IsInfinite()) {28      result.flags.set(RealFlag::InvalidArgument);29    }30  } else {31    bool negativePower{power.IsNegative()};32    INT absPower{power.ABS().value};33    REAL squares{base};34    int nbits{INT::bits - absPower.LEADZ()};35    for (int j{0}; j < nbits; ++j) {36      if (j > 0) { // avoid spurious overflow on last iteration37        squares =38            squares.Multiply(squares, rounding).AccumulateFlags(result.flags);39      }40      if (absPower.BTEST(j)) {41        if (negativePower) {42          result.value = result.value.Divide(squares, rounding)43                             .AccumulateFlags(result.flags);44        } else {45          result.value = result.value.Multiply(squares, rounding)46                             .AccumulateFlags(result.flags);47        }48      }49    }50  }51  return result;52}53 54template <typename REAL, typename INT>55ValueWithRealFlags<REAL> IntPower(const REAL &base, const INT &power,56    Rounding rounding = TargetCharacteristics::defaultRounding) {57  REAL one{REAL::FromInteger(INT{1}).value};58  return TimesIntPowerOf(one, base, power, rounding);59}60} // namespace Fortran::evaluate61#endif // FORTRAN_EVALUATE_INT_POWER_H_62