Passing a pointer to an array of arrays to a function - c++

I have a main function which sets up the following variables:
double matrix[numVectors][size] = {
{0.183963, 0.933146, 0.476773, 0.086125, 0.566566, 0.728107, 0.837345, 0.885175, 0.600559, 0.142238},
{0.086523, 0.025236, 0.252289, 0.089437, 0.382081, 0.420934, 0.038498, 0.626125, 0.468158, 0.247754},
{0.969345, 0.127753, 0.736213, 0.264992, 0.518971, 0.216767, 0.390992, 0.242241, 0.516135, 0.990155}
};
double result1[size], result2[size];
double *ptr_matrix = &matrix[0];
double *ptr_result1 = &result1[0];
double *ptr_result2 = &result2[0];
What the above is trying to do is:
Create an array with three rows of 10 doubles
Create two empty arrays of 10 doubles
Create a pointer to the matrix
Create pointers to the two empty arrays
Then, I'm trying to pass all three pointers to another function. This other function will iterate over the matrix rows (only the rows, it doesn't visit the whole matrix space), perform a computation using the row (as an array). The end result is the two empty arrays declared at the beginning end up each becoming one row from the matrix.
Here is the prototype of the second function:
void smallestSum(double (*mat)[size], int num, double *first, double *second)
This function goes through each combination of the matrix rows (0/1, 0/2, 1/2) and checks the sums of their values. The two arrays producing the smallest sum eventually become result1 and result2 from above.
Seeing as this is the first time I'm really delving into pointer/array/matrix territory, I have a few questions:
Am I correctly "getting" a pointer to the matrix? Or do I need to get a pointer to the first value of the matrix instead?
In smallestSum(), can I iterate over the array as I would normally (using for (int i = 0; i < num; i++)?

You need to change the definition of ptr_matrix, as it's not a pointer to a single double, but to the whole row:
double (*ptr_matrix)[size] = &matrix[0];
Then, you can call the function as follows:
smallestSum(ptr_matrix, numVectors, ptr_result1, ptr_result_2);
Inside smallestSum, you can iterate both over rows and over columns.
Note that size must be known at compilation time.
If the function doesn't modify the matrix, consider adding const to the type of its first argument.

The answer abacabadabacaba gave is mostly correct except that size does not need to be known at compile time. If you include size as a parameter to the function you can use it as part of the type for other parameters to that function:
void smallestSum(int size, double (*mat)[size], int num, double *first, double *second)

Related

How to use accumulate function to sum a row of values in a variable array?

I've been working on a program where I need to be able to sum rows in a two-dimensional array whose number of columns are variables. I should also add that the rows are "split" into two parts (part A, and part B) whose sizes depend on user input.
I can obviously sum a row just using a for loop, but I wanted a more elegant solution that would also be easier to set up across the whole program. I stumbled across the accumulate function out of the numeric library, but all examples that I was able to find were exclusively for one-dimensional arrays.
Here's a sample of my problem code:
total = partNum[PART_A] + partNum[PART_B];
partStart[PART_A] = 0;
partEnd[FUNC_A] = partNum[PART_A];
partStart[PART_B] = partNum[PART_A];
partEnd[FUNC_B] = total;
double stat[5][total];
double mass_sum = 0.0
func = PART_A;
accumulate(stat[MASS][partStart[func]], stat[MASS][partStart[func]], mass_sum);
However, I get a buildtime error which states that:
Indirection requires pointer operand ('double' invalid')
I assume this is a syntax error, but changing how I defined the array's start and end did nothing to fix the error.
The two first argument of accumulate are iterators that the function will use to iterate over the range, but you are passing actual element of the array
Iterator in C++ is a concept that requires certain operations to be valid on your object, as defined per the standard. For instance, pointer types usually match the LegacyRandomAccessIterator, meaning that you can basically use them to as array-like object (you can increment them with ++, you can indirect them with *, you can access an element at position i with [], etc.). I won't go into full details about what are iterators in C++ because it's a whole topic and you can find plenty of references, in particular on the two links I provided.
Back to your problem, what you want is to give accumulate iterator to the beginning and the end of your row, or the beginning and the end of your subranges. There are two ways to do this:
Take the address of the element stat[MASS][partStart[func]], i.e., &stat[MASS][partStart[func]], which will give you the beginning of the range, and then &stat[MASS][partEnd[func]] will give you the end of the range. This works because stat is as double stat[5][total] and the access operator ([]) gives you a reference (a double&), that you can take the address of, and the element on the row are contiguous in memory (that would not work for a column).
Use stat[MASS] + partStart[func] and stat[MASS] + partEnd[func]. In this case, you take the beginning of the row (stat[MASS]), which is (or is implicitly convertible to) a pointer to double (double*) and you increment that pointer by partStart[func] or partEnd[func], giving you the addresses of the elements you want in the row.
So basically:
std::accumulate(&stat[MASS][partStart[func]], &stat[MASS][partEndfunc]], mass_sum);
// or
std::accumulate(stat[MASS] + partStart[func], stat[MASS] + partEnd[func], mass_sum);

Operations with arrays

I have to code a program using C++ at university.
They asked me to type all elements of a 3x3 matrix. And all elements have to be positive. So far so good. Each row of the matrix represents the components of a R^3 vector. So there are three vectors (Three 1D arrays). I had to calculate the modulus of each vector and successfully did it.
Here comes the problem... The next step is to get which vector the largest modulus has, and return its position. All this using a function --> int largestModulus (int Modulus[3]). How can I do that? Because it is all about comparing but this time is comparing a vector, and I only know how to compare different single elements. Thanks for your help!!
In the arguments to the function,
since you're passing and receiving a 2D matrix, the parameter must be
int largestModulus (int Modulus[][3])

Passing an array of structure elements

I am doing some vector computations using the NE10 library. The library has a type for a complex number which is a struct like this:
typedef struct
{
ne10_float32_t r;
ne10_float32_t i;
} ne10_fft_cpx_float32_t;
I would like to have a function, which takes an array of these structs (1D array of complex numbers) as an argument and performs a vector computation for only the r or i elements of the array. Here is an example of such function to get an idea:
void multiple_real_part_by_two(ne10_fft_cpx_float32_t* output,
ne10_fft_cpx_float32_t* input, ne10_uint32_t array_length)
{
ne10_mulc_float_c (&output->r, &input->r, 2.0, array_length)
}
So I would like the output array to be like the input array, but each of the r elements should be multiplied by two. The problem is, the way the function is written above does not work, and leads to a segmentation fault. I think the problem is in how I am trying to pass an array of the r elements to the ne10_mulc_float_c() function.
The ne10_mulc_float_c() function takes as arguments pointers to two arrays of type ne10_float32_t of size array_length. The elements of the input array are multiplied by the number passed as the third argument, and the result is stored in the output array. The documentation can be found here.
Is there a way I could do this? I know I could just do this in a for loop
for (int i = 0; i < array_length; i++) {
output[i].r = input[i].r * 2.0
}
but I don't want to do this since performance is critical, which is why I am trying to use the vector operations provided by NE10 in the first place.
The problem is that you give ne10_mulc_float_c() arguments of the right type, but which do not match the assumptions.
According to the library's documentation page, the function is defined as:
ne10_result_t ne10_mulc_float_c (ne10_float32_t *dst, ne10_float32_t *src,
const ne10_float32_t cst, ne10_uint32_t count)
with the following arguments:
[out] dst Pointer to the destination array
[in] src Pointer to the source array
[in] cst The constant to multiply by
[in] count The number of scalar values to be processed
This means that the function assumes that dst and src are are pointers to arrays of count CONSECUTIVE floating point numbers.
Unfortunately, the is is not the case with the arguments that you pass:
&output->r and &input->r are both pointers to one single float. So as soon at this function tries to access the second item in the array it expects, it code goes beyond the array's real bounds and this is UB. This is why it doesn't work and you get the segmentation fault.
Your for-loop is just fine. Don't forget:
Premature optimization is the root of all evil.
-- Donald Knuth

map range of float values to single value in c++

I have array of key-frames that looks as
sruct key-frame
{ float time;
matrix4x4 transformMatrix;}
array is sorted according to time value. Also I have
float value;
I access this array millions of times. Array itself remains unchanged. My goal is to find index of first keyframe that has time bigger then value. Can this be done in constant time? Does c++ has something that maps not overlaping ranges of values to particular value?
The std::upper_bound function will do exactly this in O(log n) time for collections that support random access iterators (yours most surely does.) You'll need to tell it how to compare the structs, which you can do with a lambda function like so:
auto keyframe_iterator =
std::upper_bound(keyframes.begin(), keyframes.end(), value,
[](const keyframe& a, const keyframe& b) { a.time < b.time; });`

Are functions on matrices applied to the entire matrix or each row in Fortran?

I've never written in Fortran, but I'm trying to adapt a script to R and the following lines are confusing me. So this is how the variable is defined:
real, dimension(n,nd) :: x
Does this mean x is n arrays filled with nd number of real values or a n x nd matrix?
Then
amax = maxval(abs(x))
x = x/amax
is applied. Is the variable amax a global max of the absolute values in x or is it an array of n max values, one for each row? This is important to know if the x = x/amax is being applied to each row or the entire matrix. The purpose of this function seems to be some type of normalization.
The question of the title is much more general than that of the body, so I'll come to that later.
The result of maxval(array) is a scalar, being the maximum value in array (if it's of non-zero size).
In your example, x is a single array of rank 2 (which is commonly thought of as being a matrix). Thus, maxval(x) is indeed what you call the global maximum of that matrix. An alternative form of maxval is required to give the row-by-row maxima: maxval(x,dim=2).
Now, there is something else to note from your example:
x = x/amax
has a requirement about the shapes of x and amax.
You don't give a declaration for amax but there are two possibilities:
amax has the same shape as x; or
amax is a scalar.
[Note that amax needn't be a scalar just because it is assigned a scalar result from that maxval reference. However, you will see that amax won't be declared as rank 1 with size the number of rows of x, so that's another clue that maxval is giving the global maximum.]
These two possibilities come from conformability rules for division. With amax a scalar each element of x is divided by that value; with amax an array each element of x is divided by the corresponding element in amax.
If you want to normalize each individual row of x then you just can't use that division expression with amax a rank 1 array.
Coming to the more general question: even though it's an either/or question the answer is "no". There is no single way. Each function acts as it is defined.
As a general rule, though, the intrinsic functions of Fortran rarely care about the specific case of arrays which have "rows". But one useful thought is that a function acts either:
on all elements individually, returning an array of the same shape;
on the array as a whole, returning a scalar.
Moderated by the fact that many will have this dim argument which causes the function to act on slices instead.
The first line means that the variable x is an array of two dimensions (n,nd) and not n arrays of nd values. The function maxval returns the maximum value in this array.
See page 130 (in the PDF not the printed number) in F90_notes.pdf (you will also find a whole chapter concerning the arrays in the same document).
To add to Baruchel's answer: x/amax divides each element of the 2D array x by the scalar amax.