9#ifndef FORTRAN_EVALUATE_INT_POWER_H_
10#define FORTRAN_EVALUATE_INT_POWER_H_
14#include "flang/Evaluate/real.h"
15#include "flang/Evaluate/target.h"
19template <
typename REAL,
typename INT>
21 const INT &power,
bool forceMultiply =
false,
22 Rounding rounding = TargetCharacteristics::defaultRounding) {
24 if (base.IsNotANumber()) {
25 result.value = REAL::NotANumber();
26 result.flags.set(RealFlag::InvalidArgument);
27 }
else if (power.IsZero()) {
28 if (base.IsZero() || base.IsInfinite()) {
29 result.flags.set(RealFlag::InvalidArgument);
32 bool negativePower{!forceMultiply && power.IsNegative()};
33 INT absPower{power.ABS().value};
35 int nbits{INT::bits - absPower.LEADZ()};
36 for (
int j{0}; j < nbits; ++j) {
39 squares.Multiply(squares, rounding).AccumulateFlags(result.flags);
41 if (absPower.BTEST(j)) {
43 result.value = result.value.Divide(squares, rounding)
44 .AccumulateFlags(result.flags);
46 result.value = result.value.Multiply(squares, rounding)
47 .AccumulateFlags(result.flags);
55template <
typename W,
int P,
typename INT>
58 Rounding rounding = TargetCharacteristics::defaultRounding) {
60 REAL one{REAL::FromInteger(INT{1}).value};
62 TimesIntPowerOf(one, base, power,
false, rounding)};
63 if (result.flags.test(RealFlag::Overflow) && power.IsNegative() &&
64 !base.IsZero() && base.ABS().Compare(one) == Relation::Greater) {
66 REAL recip{one.Divide(base, rounding).AccumulateFlags(retry.flags)};
68 TimesIntPowerOf(one, recip, power,
true, rounding)
69 .AccumulateFlags(retry.flags);
75template <
typename REAL,
typename INT>
77 Rounding rounding = TargetCharacteristics::defaultRounding) {
78 REAL one{REAL::FromInteger(INT{1}).value};
79 return TimesIntPowerOf(one, base, power,
false, rounding);
Definition target-rounding.h:18