0

I'm using a C++ compiler but writing code in C (if that helps)

There's a series of numbers

(-1^(a-1)/2a-1)B^(2a-1)

A and X are user defined... A must be positive, but X can be anything (+,-)...

to decode this sequence... I need use exponents/powers, but was given some restrictions... I can't make another function, use recursion, or pow() (among other advanced math functions that come with cmath or math.h).

There were plenty of similar questions, but many answers have used functions and recursion which aren't directly relevant to this question.

This is the code that works perfectly with pow(), I spent a lot of time trying to modify it to replace pow() with my own code, but nothing seems to be working... mainly getting wrong results. X and J are user inputted variables

for (int i = 1; i < j; i++) 
    sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
}
A P
  • 2,131
  • 2
  • 24
  • 36
  • 3
    *I have a sequence of numbers and I need to fit in pow(),* - what does it mean? What exactly do you need to do? – Eugene Sh. Nov 05 '21 at 17:28
  • 3
    A simple `for` loop should work. – 001 Nov 05 '21 at 17:28
  • 1
    @JohnnyMopp Unless it is a fractional power :P – Eugene Sh. Nov 05 '21 at 17:30
  • @EugeneSh. fixed the quesion – A P Nov 05 '21 at 17:38
  • 1
    Well, `pow(-1, i - 1)` is trivial. `-1` in an odd power is `-1`, in even power its `1`. – Eugene Sh. Nov 05 '21 at 17:39
  • Also it looks like some kind of sum of series, which, while I fail to recognize at the moment, has likely a closed form solution. – Eugene Sh. Nov 05 '21 at 17:41
  • @EugeneSh.: Looks like one of the trig functions to me. – Bathsheba Nov 05 '21 at 17:46
  • 2
    If the exponents are integers, you can use a binary exponentiation algorithm (exponentiation by squaring), combined with a reciprocal operation if the exponent is negative. But since the exponent is increasing a constant amount each iteration, this algorithm is overkill. – Ian Abbott Nov 05 '21 at 17:48
  • @Bathsheba My bets are on sine, but I'm not sure the posted formula is correct. – Bob__ Nov 05 '21 at 17:48
  • Please note that all those successive powers can be evaluated by repeatedly multiplying `x` by `x * x`. – Bob__ Nov 05 '21 at 17:56
  • 1
    Note that you don't really need `pow` at all. Recognise that pow(x, y + 1) = x * pow(x, y) and use that recurrence relation when evaluating the terms in your expression. – Bathsheba Nov 05 '21 at 17:56
  • @Bob__ i am aware of that, this is the code snippet as of now... and i need to factor out the POW parts - for (int i = 1, coef=1, pw=1; i < n + 1; ++i) { //i starts at 1, then stops at N (user generated number) sum = (Pow(-1, i - 1)) / (2 * i - 1) * (Pow(x, 2 * i - 1)) + sum; } – A P Nov 05 '21 at 17:58
  • Look at the accepted answer here: https://stackoverflow.com/questions/34703147/sine-function-without-any-library/34703167 There are many other dupes on the subject, but please note that the formula in the code you posted is different. – Bob__ Nov 05 '21 at 18:06
  • @Bob__ thank you, yes very different , but I hope I can learn something from it ;) – A P Nov 05 '21 at 18:08
  • As @IanAbbott. With an integer power, please see [The most efficient way to implement an integer based power function pow(int, int)](https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int). Although the base operand is integer too in that question, the technique works well with floating point – it is the integer power that is decomposed. – Weather Vane Nov 05 '21 at 18:18
  • @WeatherVane Yes, that is the algorithm I was referring to, but it is overkill for this iterative calculation. – Ian Abbott Nov 05 '21 at 18:26
  • Concerning your C and C++ mix: If you're compiling with a C++ compiler, the code must be seen as C++ as well. Pick one language and the correct compiler for it. – Ulrich Eckhardt Nov 06 '21 at 10:44
  • I solved the solution on my own, but thanks for the input... since the question is closed... it's not worth putting my own answer in... But I hope this can help others – A P Nov 08 '21 at 09:34
  • 1
    @APA I ported the power by squaring to single expression macro (edit1 in my answer). – Spektre Nov 08 '21 at 10:11

2 Answers2

2

You can use macros to get away with no function calls restriction as macros will generate inline code which is technically not a function call

however in case of more complex operations macro can not have return value so you need to use some local variable for the result (in case of more than single expression) like:

int ret;
#define my_pow_notemp(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
#define my_pow(a,b)\
    {\
    ret=1;\
    if (int(b& 1)) ret*=a;\
    if (int(b& 2)) ret*=a*a;\
    if (int(b& 4)) ret*=a*a*a*a;\
    if (int(b& 8)) ret*=a*a*a*a*a*a*a*a;\
    if (int(b&16)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
    if (int(b&32)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
    }
void main()
   {
   int a=2,b=3,c;
   c=my_pow_notemp(a,b); // c = a^b
   my_pow(a,b); c = ret; // c = a^b
   }

as you can see you can use my_pow_notemp directly but the code is hardcoded so only up to a^3 if you want more you have to add it to code. The my_pow is accepting exponents up to a^63 and its also an example on how to return value in case of more complex code inside macro. Here are some (normal) ways on how to compute powers in case you need non integer or negative exponents (but to convert it to unrolled code will be insanely hard without loops/recursion):

In case you want to get away with recursion and function calls you can use templates instead of macros but that is limited to C++.

template<class T> T my_pow(T a,T b)
    {
    if (b==0) return 1;
    if (b==1) return a;
    return a*my_pow(a,b-1);
    }
void main()
   {
   int a=2,b=3,c;
   c=my_pow(a,b);
   }

As you can see templates have return value so no problem even with more complex code (more than single expression).

To avoid loops you can use LUT tables

int my_pow[4][4]=
    {
    {1,0,0,0},  // 0^
    {1,1,1,1},  // 1^
    {1,2,4,8},  // 2^
    {1,3,9,27}, // 3^
    };
void main()
   {
   int a=2,b=3,c;
   c=my_pow[a][b];
   }

If you have access to FPU or advanced math assembly you can use that as asm instruction is not a function call. FPU usually have log,exp,pow functions natively. This however limits the code to specific instruction set !!!

Here some examples:

So when I consider your limitation I think the best way is:

#define my_pow(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
void main()
   {
   int a=2,b=3,c;
   c=my_pow(a,b); // c = a^b
   }

Which will work on int exponents b up to 3 (if you want more just add (b==4)?a*a*a*a: ... :0) and both int and float bases a. If you need much bigger exponent use the complicated version with local temp variable for returning result.

[Edit1] ultimative single expression macro with power by squaring up to a^15

#define my_pow(a,b) (1* (int(b&1))?a:1* (int(b&2))?a*a:1* (int(b&4))?a*a*a*a:1* (int(b&8))?a*a*a*a*a*a*a*a:1)
void main()
   {
   int a=2,b=3,c;
   c=my_pow(a,b); // c = a^b
   }

In case you want more than a^15 just add sub term (int(b&16))?a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a:1 and so on for each bit of exponent.

Spektre
  • 49,595
  • 11
  • 110
  • 380
1

It is a series. Replace pow() based on the previous iteration. @Bathsheba

Code does not need to call pow(). It can form pow(x, 5 * i - 1) and pow(-1, i - 1), since both have an int exponent based on the iterator i, from the prior loop iteration.

Example:
Let f(x, i) = pow(x, 5 * i - 1)
Then f(x, 1) = x*x*x*x
and f(x, i > 1) = f(x, i-1) * x*x*x*x*x

double power_n1 = 1.0; 
double power_x5 = x*x*x*x; 
for (int i = 1; i < j + 1; i++) 
  // sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
  sum += power_n1 / (5 * i - 1) * power_x5;
  power_n1 = -power_n1;
  power_x5 *= x*x*x*x*x; 
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256