306

What is the most efficient way given to raise an integer to the power of another integer in C?

// 2^3
pow(2,3) == 8

// 5^5
pow(5,5) == 3125
durron597
  • 31,968
  • 17
  • 99
  • 158
Doug T.
  • 64,223
  • 27
  • 138
  • 202
  • Doesn't C have a pow() function? – jalf May 30 '09 at 13:07
  • 27
    yes, but that works on floats or doubles, not on ints – Nathan Fellman May 30 '09 at 13:46
  • 7
    When you say "efficiency," you need to specify efficient in relation to what. Speed? Memory usage? Code size? Maintainability? – Andy Lester Oct 02 '08 at 17:26
  • 3
    If you're sticking to actual `int`s (and not some huge-int class), a lot of calls to ipow will overflow. It makes me wonder if there's a clever way to pre-calculate a table and reduce all the non-overflowing combinations to a simple table lookup. This would take more memory than most of the general answers, but perhaps be more efficient in terms of speed. – Adrian McCarthy Jan 07 '16 at 17:15
  • 1
    `pow()` not a safe function – EsmaeelE Oct 29 '17 at 15:42
  • As pow will easily overflow, either you add checks for that (and thus make it slower), or use unsigned integers and let it wrap around and keep the performance. – alx - recommends codidact Mar 17 '19 at 23:15

20 Answers20

444

Exponentiation by squaring.

int ipow(int base, int exp)
{
    int result = 1;
    for (;;)
    {
        if (exp & 1)
            result *= base;
        exp >>= 1;
        if (!exp)
            break;
        base *= base;
    }

    return result;
}

This is the standard method for doing modular exponentiation for huge numbers in asymmetric cryptography.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
Elias Yarrkov
  • 4,589
  • 1
  • 16
  • 6
  • With maybe break-out special cases for small exponents known to have better algorithms: turns out the questioner doesn't expect overflow anyway, so these are presumably common. – Steve Jessop Sep 19 '08 at 13:18
  • AKA the "fast exponentiation algorithm". – wnoise Sep 20 '08 at 04:49
  • 1
    Thanks for the code Elias. I beautified the code a bit for better presentation. – Ashwin Nanjappa May 30 '09 at 12:58
  • 51
    You should probably add a check that "exp" isn't negative. Currently, this function will either give a wrong answer or loop forever. (Depending on whether >>= on a signed int does zero-padding or sign-extension - C compilers are allowed to pick either behaviour). – user9876 Jul 28 '09 at 16:42
  • 2
    GSL's gsl_sf_pow_int implements this, including the negative case handling: http://www.gnu.org/software/gsl/manual/html_node/Power-Function.html – Rhys Ulerich Apr 14 '10 at 22:29
  • 32
    I wrote a more optimized version of this, freely downloadable here: https://gist.github.com/3551590 On my machine it was about 2.5x faster. – orlp Aug 31 '12 at 11:18
  • 13
    @AkhilJain: It's perfectly good C; to make it valid also in Java, replace `while (exp)` and `if (exp & 1)` with `while (exp != 0)` and `if ((exp & 1) != 0)` respectively. – Ilmari Karonen Apr 08 '13 at 16:38
  • 5
    Your function should probably have `unsigned exp`, or else handle negative `exp` properly. – Craig McQueen Aug 21 '13 at 00:40
  • This may not be the most optimal solution, see http://stackoverflow.com/a/445351/632951 – Pacerier Sep 16 '14 at 09:11
  • Anyone explains why this method is better than the easiest way of just multiplying n times? – Ascendant Nov 07 '14 at 01:51
  • Do you know the complexity of this algorithm in Big O notation? – Algorithmatic Jan 20 '15 at 18:05
  • 1
    it has has Overflow error. Does not work for large numbers e,.g pow(71045970,41535484) – Anushree Acharjee Jul 10 '15 at 05:23
  • 3
    @AnushreeAcharjee: That's a domain error anyway. No C implementation can represent that value in an integral type. You'd need a 28*41535484 bit type for that. – MSalters Aug 13 '15 at 09:28
  • 8
    @ZinanXing Multiplying n times results in more multiplications and is slower. This method saves multiplications by effectively reusing them. E.g., to calculate n^8 the naïve method of `n*n*n*n*n*n*n*n` uses 7 multiplications. This algorithm instead computes `m=n*n`, then `o=m*m`, then `p=o*o`, where `p` = n^8, with just three multiplications. With large exponents the difference in performance is significant. – bames53 Oct 11 '15 at 22:40
  • should the return type be changed to `long int`? – artm Dec 06 '15 at 11:20
  • wow; pow(200, 4) takes 25 Clocks on my machine via QueryPerformanceCounter. This implementation rewritten as a macro takes 0-1 clocks! That's literally awesome. – Dmytro Sep 18 '17 at 21:48
  • 1
    If you care about overflow in `base *= base`, you should check for it: `if (abs(base) > sqrt(INT_MAX)) {break;}`. If you don't care about overflow, you should use `unsigned base` and just let it wrap around. – alx - recommends codidact Mar 17 '19 at 17:27
  • 1
    If this is "the standard method", there must be a standard implementation. Could you link to it? – ivan_pozdeev May 05 '19 at 04:33
  • 2
    Why do you use `for (;;)` instead of `while (true)`? – Peter Schorn Aug 04 '20 at 18:12
  • `for (;;)` is usually considered the more canonical way to do it – b264 Feb 26 '23 at 01:13
91

Note that exponentiation by squaring is not the most optimal method. It is probably the best you can do as a general method that works for all exponent values, but for a specific exponent value there might be a better sequence that needs fewer multiplications.

For instance, if you want to compute x^15, the method of exponentiation by squaring will give you:

x^15 = (x^7)*(x^7)*x 
x^7 = (x^3)*(x^3)*x 
x^3 = x*x*x

This is a total of 6 multiplications.

It turns out this can be done using "just" 5 multiplications via addition-chain exponentiation.

n*n = n^2
n^2*n = n^3
n^3*n^3 = n^6
n^6*n^6 = n^12
n^12*n^3 = n^15

There are no efficient algorithms to find this optimal sequence of multiplications. From Wikipedia:

The problem of finding the shortest addition chain cannot be solved by dynamic programming, because it does not satisfy the assumption of optimal substructure. That is, it is not sufficient to decompose the power into smaller powers, each of which is computed minimally, since the addition chains for the smaller powers may be related (to share computations). For example, in the shortest addition chain for a¹⁵ above, the subproblem for a⁶ must be computed as (a³)² since a³ is re-used (as opposed to, say, a⁶ = a²(a²)², which also requires three multiplies).

Pramod
  • 9,256
  • 4
  • 26
  • 27
  • 6
    @JeremySalwen: As this answer states, binary exponentiation is not in general the most optimal method. There are no efficient algorithms currently known for finding the minimal sequence of multiplications. – Eric Postpischil Dec 27 '13 at 21:32
  • 3
    @EricPostpischil, That depends on your application. Usually we don't need a *general* algorithm to work for **all** numbers. See The Art of Computer Programming, Vol. 2: Seminumerical Algorithms – Pacerier Sep 16 '14 at 09:03
  • 3
    There's a good exposition of this exact problem in _[From Mathematics to Generic Programming](http://www.fm2gp.com)_ by Alexander Stepanov and Daniel Rose. This book should be on the shelf of every software practitioner, IMHO. – Toby Speight Oct 19 '15 at 10:03
  • 2
    See also https://en.wikipedia.org/wiki/Exponentiation#Efficient_computation_with_integer_exponents. – lhf Apr 14 '16 at 11:27
  • This could be optimized for integers because there are well under 255 integer powers that will not cause overflow for 32 bit integers. You could cache the optimal multiplication structure for each int. I imagine the code+data would still be smaller than simply caching all powers... – Josiah Yoder Aug 17 '18 at 19:25
  • Great answer, thank you ! This can be implemented we templates or constexpr in C++ – Kiruahxh Oct 26 '20 at 17:01
30

If you need to raise 2 to a power. The fastest way to do so is to bit shift by the power.

2 ** 3 == 1 << 3 == 8
2 ** 30 == 1 << 30 == 1073741824 (A Gigabyte)
Jake
  • 2,106
  • 1
  • 24
  • 23
  • Is there an elegant way to do this so that 2 ** 0 == 1 ? – Rob Smallshire Nov 23 '11 at 21:39
  • @RobSmallshire Maybe `2 ** x = 1 << x` (as 1<<0 is 1, you'll have to check if it's in the C std, or if it's platform dependant, but you could do also `2 ** x = x ? (1 << x) : 1` note that `2 ** x` has a meaning in C, and that's not power :) – Déjà vu May 06 '21 at 06:47
12

Here is the method in Java

private int ipow(int base, int exp)
{
    int result = 1;
    while (exp != 0)
    {
        if ((exp & 1) == 1)
            result *= base;
        exp >>= 1;
        base *= base;
    }

    return result;
}
user1067920
  • 1,492
  • 15
  • 8
  • does not work for large numbes e.g pow(71045970,41535484) – Anushree Acharjee Jul 10 '15 at 05:26
  • 23
    @AnushreeAcharjee of course not. Computing such a number would require arbitrary precision arithmetic. – David Etler Sep 04 '15 at 21:13
  • 1
    Use BigInteger#modPow or Biginteger#pow for big numbers, appropriate algorithms based on size of arguments are already implemented – Raman Yelianevich Nov 24 '15 at 18:15
  • 1
    On the one hand, the question was tagged by the OP as C, so it is clearly a C question. Moreover, these kind of microoptimizations are not usually done in such high level languages (performance is not what you're after, if you use Java, I guess). On the other hand, if this question is high in search engines, it might be interesting to expand it to other languages too. So, never mind my old comment :) – alx - recommends codidact Apr 25 '21 at 20:39
  • @AnushreeAcharjee : yeah youve also forgotten that `71045970 ^ 41535484` has `326mn` digits in decimal – RARE Kpop Manifesto May 18 '23 at 13:52
8

An extremely specialized case is, when you need say 2^(-x to the y), where x, is of course is negative and y is too large to do shifting on an int. You can still do 2^x in constant time by screwing with a float.

struct IeeeFloat
{

    unsigned int base : 23;
    unsigned int exponent : 8;
    unsigned int signBit : 1;
};


union IeeeFloatUnion
{
    IeeeFloat brokenOut;
    float f;
};

inline float twoToThe(char exponent)
{
    // notice how the range checking is already done on the exponent var 
    static IeeeFloatUnion u;
    u.f = 2.0;
    // Change the exponent part of the float
    u.brokenOut.exponent += (exponent - 1);
    return (u.f);
}

You can get more powers of 2 by using a double as the base type. (Thanks a lot to commenters for helping to square this post away).

There's also the possibility that learning more about IEEE floats, other special cases of exponentiation might present themselves.

Doug T.
  • 64,223
  • 27
  • 138
  • 202
  • Nifty solution, but unsigend?? – paxdiablo Sep 19 '08 at 12:37
  • An IEEE float is base x 2 ^ exp, changing the exponent value won't lead to anything else than a multiplication by a power of two, and chances are high it will denormalize the float ... your solution is wrong IMHO – Drealmer Sep 19 '08 at 12:50
  • You are all correct, I misremembered that my solution was originally written, oh so long ago, for powers of 2 explicitly. I've rewritten my answer to be a special case solution to the problem. – Doug T. Sep 19 '08 at 12:57
  • Firstly, the code is broken as quoted, and requires editing to get it to compile. Secondly the code is broken on a core2d using gcc. see [this dump](http://pastebin.com/m70045534) Perhaps I did something wrong. I however do not think this will work, since the IEEE float exponent is base 10. – freespace Sep 19 '08 at 12:58
  • 3
    Base 10? Uh no, it's base 2, unless you meant 10 in binary :) – Drealmer Sep 19 '08 at 13:02
  • Doesn't seem to work for powers of 2 either... I would like to see this in action, can some one spot my mistake in my previous pastebin? Also, embrassingly, I made an error in my previous comment, and said base 10 when I _really_ wanted base 2 ;) – freespace Sep 19 '08 at 13:03
  • You still should be multiplying the exponents, not adding them. And look into CPU-specific implementations. For instance on x86, bsr to find the hibit will be no slower than an int->double conversion and probably faster. – Steve Jessop Sep 19 '08 at 13:12
  • Just noticed that you're now calculating pow(2,n). This can be done in a single CPU instruction on most platforms with 1 << n, except that you must range-check n first, since 1 << 32 is undefined behaviour. – Steve Jessop Sep 19 '08 at 13:23
  • Thanks for humbling me, seriously. I completely misremembered something I did long ago, and was corrected. Thank god too, because someone might have tried to run with my solution! If you voted me up, feel completely free to undo it – Doug T. Sep 19 '08 at 13:24
  • -1 useless; exponentiating 2 is more easily performed by bitshifting. Also bitfields have unspecified order within the larger type so this code is not portable even across compilers with the same (IEEE) float implementation. Further, you need `signed char` if you claim your comment is correct, as the signedness of char is unspecified. – R.. GitHub STOP HELPING ICE Jul 20 '10 at 14:07
7

power() function to work for Integers Only

int power(int base, unsigned int exp){

    if (exp == 0)
        return 1;
    int temp = power(base, exp/2);
    if (exp%2 == 0)
        return temp*temp;
    else
        return base*temp*temp;

}

Complexity = O(log(exp))

power() function to work for negative exp and float base.

float power(float base, int exp) {

    if( exp == 0)
       return 1;
    float temp = power(base, exp/2);       
    if (exp%2 == 0)
        return temp*temp;
    else {
        if(exp > 0)
            return base*temp*temp;
        else
            return (temp*temp)/base; //negative exponent computation 
    }

} 

Complexity = O(log(exp))

roottraveller
  • 7,942
  • 7
  • 60
  • 65
  • How is this different from the answers of [Abhijit Gaikwad](http://stackoverflow.com/a/24299375/3789665) and [chux](http://stackoverflow.com/a/29396800/3789665)? Please argue the use of `float` in the second code block presented (consider showing how `power(2.0, -3)` gets computed). – greybeard Jan 07 '16 at 20:27
  • @greybeard I have mentioned some comment. may be that can resolve your query – roottraveller Jan 08 '16 at 03:34
  • 1
    GNU Scientific Library already has your second function: https://www.gnu.org/software/gsl/manual/html_node/Small-integer-powers.html – alx - recommends codidact Mar 17 '19 at 18:17
  • @roottraveller could you please explain ```negative exp and float base``` solution? why we use temp, separate exp by 2 and check exp (even/odd)? thanks! – Leon Mar 23 '20 at 22:27
6
int pow( int base, int exponent)

{   // Does not work for negative exponents. (But that would be leaving the range of int) 
    if (exponent == 0) return 1;  // base case;
    int temp = pow(base, exponent/2);
    if (exponent % 2 == 0)
        return temp * temp; 
    else
        return (base * temp * temp);
}
Chris Cudmore
  • 29,793
  • 12
  • 57
  • 94
  • Not my vote, but `pow(1, -1)` doesn't leave the range of int despite a negative exponent. Now that one works by accident, as does `pow(-1, -1)`. – MSalters Aug 13 '15 at 09:34
  • 1
    The only negative exponent that *may* not make you leave the range of int is -1. And it only works if base is 1 or -1. So there are only two pairs (base,exp) with exp<0 that would not lead to non integer powers. Although I'm a matematician and I like quantifiers, I think in this case, in practice, it's ok to say that a negative exponent makes you leave the integer realm... – bartgol Aug 15 '17 at 15:15
6

If you want to get the value of an integer for 2 raised to the power of something it is always better to use the shift option:

pow(2,5) can be replaced by 1<<5

This is much more efficient.

Kevin Bedell
  • 13,254
  • 10
  • 78
  • 114
aditya
  • 69
  • 1
  • 2
4

Just as a follow up to comments on the efficiency of exponentiation by squaring.

The advantage of that approach is that it runs in log(n) time. For example, if you were going to calculate something huge, such as x^1048575 (2^20 - 1), you only have to go thru the loop 20 times, not 1 million+ using the naive approach.

Also, in terms of code complexity, it is simpler than trying to find the most optimal sequence of multiplications, a la Pramod's suggestion.

Edit:

I guess I should clarify before someone tags me for the potential for overflow. This approach assumes that you have some sort of hugeint library.

Jason Z
  • 13,122
  • 15
  • 50
  • 62
2

Late to the party:

Below is a solution that also deals with y < 0 as best as it can.

  1. It uses a result of intmax_t for maximum range. There is no provision for answers that do not fit in intmax_t.
  2. powjii(0, 0) --> 1 which is a common result for this case.
  3. pow(0,negative), another undefined result, returns INTMAX_MAX

    intmax_t powjii(int x, int y) {
      if (y < 0) {
        switch (x) {
          case 0:
            return INTMAX_MAX;
          case 1:
            return 1;
          case -1:
            return y % 2 ? -1 : 1;
        }
        return 0;
      }
      intmax_t z = 1;
      intmax_t base = x;
      for (;;) {
        if (y % 2) {
          z *= base;
        }
        y /= 2;
        if (y == 0) {
          break; 
        }
        base *= base;
      }
      return z;
    }
    

This code uses a forever loop for(;;) to avoid the final base *= base common in other looped solutions. That multiplication is 1) not needed and 2) could be int*int overflow which is UB.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • `powjii(INT_MAX, 63)` causes UB in `base *= base`. Consider checking that you can multiply, or move to unsigned and let it wrap around. – alx - recommends codidact Mar 17 '19 at 18:00
  • There is no reason to have `exp` be signed. It complicates the code because of the odd situation where `(-1) ** (-N)` is valid, and any `abs(base) > 1` will be `0` for negative values of `exp`, so it is better to have it unsigned and save that code. – alx - recommends codidact Mar 17 '19 at 19:38
  • 1
    @CacahueteFrito True that `y` as signed is not really needed and brings the complications you commented on, yet OP's request was specific `pow(int, int)`. Thus those good comments belong with the OP's question. As OP has not specified what to do on overflow, a well defined wrong answer is only marginally better than UB. Given "most efficient way", I doubt OP cares about OF. – chux - Reinstate Monica Mar 17 '19 at 23:01
1

more generic solution considering negative exponenet

private static int pow(int base, int exponent) {

    int result = 1;
    if (exponent == 0)
        return result; // base case;

    if (exponent < 0)
        return 1 / pow(base, -exponent);
    int temp = pow(base, exponent / 2);
    if (exponent % 2 == 0)
        return temp * temp;
    else
        return (base * temp * temp);
}
Abhijit Gaikwad
  • 3,072
  • 28
  • 37
1

In addition to the answer by Elias, which causes Undefined Behaviour when implemented with signed integers, and incorrect values for high input when implemented with unsigned integers,

here is a modified version of the Exponentiation by Squaring that also works with signed integer types, and doesn't give incorrect values:

#include <stdint.h>

#define SQRT_INT64_MAX (INT64_C(0xB504F333))

int64_t alx_pow_s64 (int64_t base, uint8_t exp)
{
    int_fast64_t    base_;
    int_fast64_t    result;

    base_   = base;

    if (base_ == 1)
        return  1;
    if (!exp)
        return  1;
    if (!base_)
        return  0;

    result  = 1;
    if (exp & 1)
        result *= base_;
    exp >>= 1;
    while (exp) {
        if (base_ > SQRT_INT64_MAX)
            return  0;
        base_ *= base_;
        if (exp & 1)
            result *= base_;
        exp >>= 1;
    }

    return  result;
}

Considerations for this function:

(1 ** N) == 1
(N ** 0) == 1
(0 ** 0) == 1
(0 ** N) == 0

If any overflow or wrapping is going to take place, return 0;

I used int64_t, but any width (signed or unsigned) can be used with little modification. However, if you need to use a non-fixed-width integer type, you will need to change SQRT_INT64_MAX by (int)sqrt(INT_MAX) (in the case of using int) or something similar, which should be optimized, but it is uglier, and not a C constant expression. Also casting the result of sqrt() to an int is not very good because of floating point precission in case of a perfect square, but as I don't know of any implementation where INT_MAX -or the maximum of any type- is a perfect square, you can live with that.

1

The O(log N) solution in Swift...

// Time complexity is O(log N)
func power(_ base: Int, _ exp: Int) -> Int { 

    // 1. If the exponent is 1 then return the number (e.g a^1 == a)
    //Time complexity O(1)
    if exp == 1 { 
        return base
    }

    // 2. Calculate the value of the number raised to half of the exponent. This will be used to calculate the final answer by squaring the result (e.g a^2n == (a^n)^2 == a^n * a^n). The idea is that we can do half the amount of work by obtaining a^n and multiplying the result by itself to get a^2n
    //Time complexity O(log N)
    let tempVal = power(base, exp/2) 

    // 3. If the exponent was odd then decompose the result in such a way that it allows you to divide the exponent in two (e.g. a^(2n+1) == a^1 * a^2n == a^1 * a^n * a^n). If the eponent is even then the result must be the base raised to half the exponent squared (e.g. a^2n == a^n * a^n = (a^n)^2).
    //Time complexity O(1)
    return (exp % 2 == 1 ? base : 1) * tempVal * tempVal 

}
ToxicAbe
  • 173
  • 1
  • 11
1
int pow(int const x, unsigned const e) noexcept
{
  return !e ? 1 : 1 == e ? x : (e % 2 ? x : 1) * pow(x * x, e / 2);
  //return !e ? 1 : 1 == e ? x : (((x ^ 1) & -(e % 2)) ^ 1) * pow(x * x, e / 2);
}

Yes, it's recursive, but a good optimizing compiler will optimize recursion away.

user1095108
  • 14,119
  • 9
  • 58
  • 116
  • Clang does optimize the tail recursion, but gcc doesn't unless you replace order of multiplication i.e. `(e % 2 ? x : 1) * pow(x * x, e / 2)` https://godbolt.org/z/EoWbfx5nc – Andy May 18 '21 at 19:30
  • @Andy I did notice `gcc` was struggling, but I don't mind, since I'm using this function as a `constexpr` function. – user1095108 May 19 '21 at 05:54
0

One more implementation (in Java). May not be most efficient solution but # of iterations is same as that of Exponential solution.

public static long pow(long base, long exp){        
    if(exp ==0){
        return 1;
    }
    if(exp ==1){
        return base;
    }

    if(exp % 2 == 0){
        long half = pow(base, exp/2);
        return half * half;
    }else{
        long half = pow(base, (exp -1)/2);
        return base * half * half;
    }       
}
Vaibhav Fouzdar
  • 199
  • 1
  • 4
0

I use recursive, if the exp is even,5^10 =25^5.

int pow(float base,float exp){
   if (exp==0)return 1;
   else if(exp>0&&exp%2==0){
      return pow(base*base,exp/2);
   }else if (exp>0&&exp%2!=0){
      return base*pow(base,exp-1);
   }
}
kyorilys
  • 822
  • 13
  • 27
0

I have implemented algorithm that memorizes all computed powers and then uses them when need. So for example x^13 is equal to (x^2)^2^2 * x^2^2 * x where x^2^2 it taken from the table instead of computing it once again. This is basically implementation of @Pramod answer (but in C#). The number of multiplication needed is Ceil(Log n)

public static int Power(int base, int exp)
{
    int tab[] = new int[exp + 1];
    tab[0] = 1;
    tab[1] = base;
    return Power(base, exp, tab);
}

public static int Power(int base, int exp, int tab[])
    {
         if(exp == 0) return 1;
         if(exp == 1) return base;
         int i = 1;
         while(i < exp/2)
         {  
            if(tab[2 * i] <= 0)
                tab[2 * i] = tab[i] * tab[i];
            i = i << 1;
          }
    if(exp <=  i)
        return tab[i];
     else return tab[i] * Power(base, exp - i, tab);
}
rank1
  • 1,018
  • 4
  • 16
  • 37
0

Here is a O(1) algorithm for calculating x ** y, inspired by this comment. It works for 32-bit signed int.

For small values of y, it uses exponentiation by squaring. For large values of y, there are only a few values of x where the result doesn't overflow. This implementation uses a lookup table to read the result without calculating.

On overflow, the C standard permits any behavior, including crash. However, I decided to do bound-checking on LUT indices to prevent memory access violation, which could be surprising and undesirable.

Pseudo-code:

If `x` is between -2 and 2, use special-case formulas.
Otherwise, if `y` is between 0 and 8, use special-case formulas.
Otherwise:
    Set x = abs(x); remember if x was negative
    If x <= 10 and y <= 19:
        Load precomputed result from a lookup table
    Otherwise:
        Set result to 0 (overflow)
    If x was negative and y is odd, negate the result

C code:

#define POW9(x) x * x * x * x * x * x * x * x * x
#define POW10(x) POW9(x) * x
#define POW11(x) POW10(x) * x
#define POW12(x) POW11(x) * x
#define POW13(x) POW12(x) * x
#define POW14(x) POW13(x) * x
#define POW15(x) POW14(x) * x
#define POW16(x) POW15(x) * x
#define POW17(x) POW16(x) * x
#define POW18(x) POW17(x) * x
#define POW19(x) POW18(x) * x

int mypow(int x, unsigned y)
{
    static int table[8][11] = {
        {POW9(3), POW10(3), POW11(3), POW12(3), POW13(3), POW14(3), POW15(3), POW16(3), POW17(3), POW18(3), POW19(3)},
        {POW9(4), POW10(4), POW11(4), POW12(4), POW13(4), POW14(4), POW15(4), 0, 0, 0, 0},
        {POW9(5), POW10(5), POW11(5), POW12(5), POW13(5), 0, 0, 0, 0, 0, 0},
        {POW9(6), POW10(6), POW11(6), 0, 0, 0, 0, 0, 0, 0, 0},
        {POW9(7), POW10(7), POW11(7), 0, 0, 0, 0, 0, 0, 0, 0},
        {POW9(8), POW10(8), 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {POW9(9), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
        {POW9(10), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    };

    int is_neg;
    int r;

    switch (x)
    {
    case 0:
        return y == 0 ? 1 : 0;
    case 1:
        return 1;
    case -1:
        return y % 2 == 0 ? 1 : -1;
    case 2:
        return 1 << y;
    case -2:
        return (y % 2 == 0 ? 1 : -1) << y;
    default:
        switch (y)
        {
        case 0:
            return 1;
        case 1:
            return x;
        case 2:
            return x * x;
        case 3:
            return x * x * x;
        case 4:
            r = x * x;
            return r * r;
        case 5:
            r = x * x;
            return r * r * x;
        case 6:
            r = x * x;
            return r * r * r;
        case 7:
            r = x * x;
            return r * r * r * x;
        case 8:
            r = x * x;
            r = r * r;
            return r * r;
        default:
            is_neg = x < 0;
            if (is_neg)
                x = -x;
            if (x <= 10 && y <= 19)
                r = table[x - 3][y - 9];
            else
                r = 0;
            if (is_neg && y % 2 == 1)
                r = -r;
            return r;
        }
    }
}
anatolyg
  • 26,506
  • 9
  • 60
  • 134
-1

My case is a little different, I'm trying to create a mask from a power, but I thought I'd share the solution I found anyway.

Obviously, it only works for powers of 2.

Mask1 = 1 << (Exponent - 1);
Mask2 = Mask1 - 1;
return Mask1 + Mask2;
MarcusJ
  • 149
  • 4
  • 12
  • I tried that, it doesn't work for 64 bit, it's shifted off never to return, and in this specific case, I'm trying to set all bits lower than X, inclusive. – MarcusJ Jun 16 '17 at 17:04
  • Was that for 1 << 64 ? That's an overflow. The largest integer is just below that: (1 << 64) - 1. – Michaël Roy Jun 16 '17 at 17:06
  • 1 << 64 == 0, that's why. Maybe your representation is best for your app. I prefer stuff that can be put in a macro, without an extra variable, like `#define MASK(e) (((e) >= 64) ? -1 :( (1 << (e)) - 1))`, so that can be computed at compile time – Michaël Roy Jun 16 '17 at 17:18
  • Yes, i know what an overflow is. Just because i didm't use that word isn't an invitation to be needlessly condescending. As i said, this works for me and it took a bit of effort to discover hence sharing it. It's that simple. – MarcusJ Jun 17 '17 at 23:11
  • I'm sorry if I offended you. I truly didn't mean to. – Michaël Roy Jun 17 '17 at 23:18
  • 1) The return value is NOT a power of 2. 2) If you want to create a 64 bit mask that has `n` ones to the right, it is easier: `uint64_t mask = (UINT64_C(1) << n) - 1;` – alx - recommends codidact Mar 17 '19 at 18:13
  • @CacahueteFrito Yeah, I know. `((1 << X) - 1)` is what I do to create LSBit masks, for MSBit it's more complicated. – MarcusJ Mar 22 '19 at 04:02
  • @MarcusJ Also you should use an explicit macro for the type of the 1. If not, you may have overflow. – alx - recommends codidact Mar 22 '19 at 11:57
  • @MarcusJ For n MSbits in a 64 bit mask: `(~(((uint64_t)UINT64_MAX) >> n))`. You answer is not related to pow. By the way, `UINT64_C` in my other comment should be replaced by `(uint64_t)`. – alx - recommends codidact Mar 22 '19 at 13:00
-1

In case you know the exponent (and it is an integer) at compile-time, you can use templates to unroll the loop. This can be made more efficient, but I wanted to demonstrate the basic principle here:

#include <iostream>

template<unsigned long N>
unsigned long inline exp_unroll(unsigned base) {
    return base * exp_unroll<N-1>(base);
}

We terminate the recursion using a template specialization:

template<>
unsigned long inline exp_unroll<1>(unsigned base) {
    return base;
}

The exponent needs to be known at runtime,

int main(int argc, char * argv[]) {
    std::cout << argv[1] <<"**5= " << exp_unroll<5>(atoi(argv[1])) << ;std::endl;
}