Assume I have an embedded system with a processor that has a FPU on it (just to be clear, I’m not talking about a specific micro-controller, I’m trying to understang the subject in a broad manner).
I wanted to create a program to evaluate the taylor series of e^x for a given x,
and only use integer and fixed point operations (without the usage of the FPU).
as a part of implementing Horner’s Rule, I find myself multiplying a float variable with an integer and taking the result into an integer variable (the round down part).
the evaluation is correct, but, how can I know if the program is going to call on the FPU to perform the multiplication ?
the specific line that I am worried about:
res += x*int_polynomial[i];
-> where x is a float variable and res,int_polynomial are integers (long and regualr)
the complete code:
#include <stdio.h>
#include <math.h>
#define N 7 // 6rd order polynomial
#define Q 15
#define E_CONST 2.718281828459045
int factor_ = 1<<Q;
float taylor_coeffs[] = {1.000000,1.000000, 0.500000, 0.166667,0.041667, 0.008333, 0.001389};
int int_polynomial[N] = {0};
void get_int_coeffs()
{
int i;
for(i = 0; i<N; i++)
{
int_polynomial[i] = taylor_coeffs[i]*factor_;
}
}
double horners_rule(float x)
{
long long res;
double res_;
int i;
for(i=0,res=0; i<N; i++)
{
res += x*int_polynomial[i];
}
return res_ = (float)res/factor_;
//OR:
// res_ = res; // insert res value into a double type variable
// return res_ /= factor_; // divide and return
}
float error_(double y, double y_hat)
{
return sqrt(pow(y-y_hat,2));
}
int main()
{
double y_hat;
float eval_error;
get_int_coeffs();
y_hat = horners_rule(1);
eval_error = error_(E_CONST,y_hat);
printf("polynomial evaluated to y_hat = %lfn",y_hat);
printf("error = %fn",eval_error);
}
I hope I am making myself clear and you guys can help me understand better 🙂
I am trying to evaluate the result of a taylor expansion of a given function, using unteger operations and fixed point operations only (without using a FPU)
1
Will my code use the FPU of the embedded system?
The short answer is yes 🙂
The longer answer:
how can I know if the program is going to call on the FPU to perform the multiplication ?
To prove it to yourself, you need to compile the code for the system you’re working on, then look at the disassembly of the binary. That’s the only way to know for sure the compiler is generating floating point operations.
For example, if you take this snippet that represents the section of your code in question and put it into godbolt.org with ARM GCC 11.2.1 and flags -mcpu=cortex-m4 -std=c17 -mfloat-abi=hard
(this is an example compiler configuration, its most important that you’re using a compiler and flags that generate code for a target MCU with a FPU on board)
int int_polynomial[7];
double horners_rule(float x)
{
long long res;
double res_;
int i;
for(i=0,res=0; i<N; i++)
{
res += x*int_polynomial[i];
}
}
Then you can see the generated FPU instructions like: vcvt.f32.s32 s14, s15
. I like godbolt because you can hover over the assembly instructions for a reminder of what each does.
To know if code will use FPU before compiling it you should learn the “Usual arithmetic conversions” rules for C. Those rules will tell you that in an expression like x * int_polynomial[i]
where x is float
and int_polynomial[i]
is int
, the value of int_polynomial[i]
will be “implicitly converted” to a float
and the expression will be evaluated as a floating point multiplication.
Pretty much any code that uses float
or double
type variables will use the FPU.