1 //===-- lib/Evaluate/int-power.h --------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef FORTRAN_EVALUATE_INT_POWER_H_
10 #define FORTRAN_EVALUATE_INT_POWER_H_
12 // Computes an integer power of a real or complex value.
14 #include "flang/Evaluate/target.h"
16 namespace Fortran::evaluate
{
18 template <typename REAL
, typename INT
>
19 ValueWithRealFlags
<REAL
> TimesIntPowerOf(const REAL
&factor
, const REAL
&base
,
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
);
31 bool negativePower
{power
.IsNegative()};
32 INT absPower
{power
.ABS().value
};
34 int nbits
{INT::bits
- absPower
.LEADZ()};
35 for (int j
{0}; j
< nbits
; ++j
) {
36 if (absPower
.BTEST(j
)) {
38 result
.value
= result
.value
.Divide(squares
, rounding
)
39 .AccumulateFlags(result
.flags
);
41 result
.value
= result
.value
.Multiply(squares
, rounding
)
42 .AccumulateFlags(result
.flags
);
46 squares
.Multiply(squares
, rounding
).AccumulateFlags(result
.flags
);
52 template <typename REAL
, typename INT
>
53 ValueWithRealFlags
<REAL
> IntPower(const REAL
&base
, const INT
&power
,
54 Rounding rounding
= TargetCharacteristics::defaultRounding
) {
55 REAL one
{REAL::FromInteger(INT
{1}).value
};
56 return TimesIntPowerOf(one
, base
, power
, rounding
);
58 } // namespace Fortran::evaluate
59 #endif // FORTRAN_EVALUATE_INT_POWER_H_