the program calculates the average geometric mean of negative elements in a 2×2 matrix,i am trying to understand code in this program below and why the author wrote what he wrote,may someone explain to me what this code below does im finding it hard to understand
what the author wrote too many pointers in the code
#include <stdio.h>
#include <math.h>
#define ROWS 2
#define COLS 2
char * last_geom_err = NULL;
float geometricMean(float * arr, int rows, int cols){
float neg_mul = 1;
int neg_count = 0;
float arr_elem;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if((arr_elem = *(arr + i * cols + j)) < 0){
neg_mul *= arr_elem;
neg_count++;
}
if (neg_count == 0){
last_geom_err = "no negative elements in array";
return 0;
}
if ((neg_count % 2 == 0) && (neg_mul < 0)){
last_geom_err = "a negative number under the square root of even degree";
return 0;
}
last_geom_err = NULL;
return pow(neg_mul, (float)neg_count);
}
int main(){
float arr[ROWS][COLS] = {
1., -2.,
-5., -6.
};
printf("Array:\n");
for(int i = 0; i < 2; i++){
for(int j = 0; j < 2; j++)
printf("%5.2f ", arr[i][j]);
putchar('\n');
}
float gm = geometricMean((float*)arr, ROWS, COLS);
if (last_geom_err != NULL)
printf("#Error of calculation: %s", last_geom_err);
else
printf("Geometric mean of negative elements of array = %5.2f", gm);
return 0;
}
why this?
char * last_geom_err = NULL;
float geometricMean(float * arr, int rows, int cols){
float neg_mul = 1;
int neg_count = 0;
float arr_elem;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if((arr_elem = *(arr + i * cols + j)) < 0){
neg_mul *= arr_elem;
neg_count++;
}
if (neg_count == 0){
last_geom_err = "no negative elements in array";
return 0;
}
if ((neg_count % 2 == 0) && (neg_mul < 0)){
last_geom_err = "a negative number under the square root of even degree";
return 0;
}
last_geom_err = NULL;
return pow(neg_mul, (float)neg_count);
}
and this one
float gm = geometricMean((float*)arr, ROWS, COLS);
if (last_geom_err != NULL)
printf("#Error of calculation: %s", last_geom_err);
else
printf("Geometric mean of negative elements of array = %5.2f", gm);
return 0
It doesn’t. First, usually the geometric mean applies only to positive numbers. One can extend the definition in a somewhat meaningful way to negative numbers by saying the geometric mean of
knegative numbers is the negative of the geometric mean of the absolute values, but what the geometric mean of a set containing both negative and positive numbers should be is unclear. Another meaningful way of extending the geometric mean would be an extension as a holomorphic function to its domain of holomorphy (which fork > 1wouldn’t be a subset of ℂk). That would include the former extension as the value on one branch above ℝ< 0k.Anyway a calculation of a geometric mean would include a
k-th root in some form, which the given programme doesn’t. Now let’s look at the code.Initialisation of the product of negative array elements and their count.
The memory layout of the matrix is
So
row 0occupies slots 0 tocols - 1,row 1occupies the slotscolsto2*cols - 1, generally,row koccupies the slotsk*colsto(k+1)*cols - 1. Thusarr + i*cols + jpoints tocol jinrow i.Read matrix element
a[i][j]and if it is negative, multiply it to the product of all negative entries and count it. Note that due to the flat memory layout, one could simply loopfor(k = 0; k < rows*cols; ++k)and accessarr[k]here.If the array contains no negative elements at all, set the error message and return. A (geometric) mean of no numbers isn’t meaningful at all.
If the number of negative entries is even and the product of negative entries is negative, set the error message and return.
Note that this is dead code. The product of an even number of negative numbers is always positive and the only caveat in floating point arithmetic (IEEE 754 conforming or sufficiently close to that; if it’s totally broken, anything could happen) is underflow, the product may become 0 although mathematically it isn’t. (Overflow isn’t an issue here, the infinities compare to 0 and behave in multiplications as they should.)
Finally, set the error message to
NULL, since no exceptional situation occurred and returnFor the geometric mean, the last line should resemble
however, that would return a NaN if
neg_mul < 0sincepowhandles negative bases only for integer exponents, so