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-exception
6//
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 iteration
37 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::evaluate
61#endif // FORTRAN_EVALUATE_INT_POWER_H_
62

source code of flang/lib/Evaluate/int-power.h