I have a function, mag, in a file mag.c that calculates the magnitude of an array.
#include <math.h>
#include "mag.h"
long double mag(long double arr[], int len){
long double magnitude=0;
for(int i=0;i<len;i++)
magnitude+=pow(arr[i],2);
magnitude=pow(magnitude,0.5);
return magnitude;
}
I would like it to accept both double and long double arrays. I've read elsewhere (for instance here) that if an argument doesn't match the function declaration, it will be implicitly converted to the correct type. I wrote a function test.c to test this.
#include <math.h>
#include <stdio.h>
#include "mag.h"
int main(){
double arr1[3]={0.0,1.1,2.2};
printf("%Lf",mag(arr1,3));
return 0;
}
However, this produced an error
test.c: In function ‘main’:
test.c:7:19: warning: passing argument 1 of ‘mag’ from incompatible pointer type [-Wincompatible-pointer-types]
printf("%Lf",mag(arr1,3));
^~~~
In file included from test.c:3:
mag.h:4:29: note: expected ‘long double *’ but argument is of type ‘double *’
long double mag(long double arr[], int len);
Declaring the array as a long double allows the function to work properly. I also tried changing the argument type in the header file, but that returned -nan. Is there any easy way to make the mag function accept both double and long double arguments, or would it be simpler to make 2 separate functions? (If I need to make separate functions for double and long double arguments, I would need to do this for a lot of files.)
... it will be implicitly converted to the correct type. I wrote a function test.c to test this.
This works for some arguments like double
converted to long double
, but not double *
converted to long double *
.
C has _Generic
just for this sort of programming. Use mag(arr, len) _Generic((arr) ...
to steer selection of code.
I recommend to also use long double
functions and long double
constants with long double
objects.
long double mag_long_double(const long double arr[], int len) {
long double magnitude = 0;
for (int i = 0; i < len; i++)
magnitude += powl(arr[i], 2); // powl
magnitude = sqrtl(magnitude);
return magnitude;
}
double mag_double(const double arr[], int len) {
double magnitude = 0;
for (int i = 0; i < len; i++)
magnitude += pow(arr[i], 2);
magnitude = sqrt(magnitude);
return magnitude;
}
#define mag(arr, len) _Generic((arr), \
long double *: mag_long_double, \
double *: mag_double \
)((arr), (len))
int main(void) {
double arr1[3] = {0.0, 1.1, 2.2};
printf("%f\n",mag(arr1,3));
long double arr2[3] = {0.0, 3.3L, 4.4L}; // Add 'L'
printf("%Lf\n",mag(arr2,3));
return 0;
}
Output
2.459675
5.500000