I have a Fortran code in which I need to sort two arrays that are related to each other. I would like to do this in a C++ function in order to leverage the built-in sort algorithm in the STL. Because Fortran is pass-by-reference, all arguments to the C++ function must be pointers. The following function esort
sorts the arrays correctly, but does not return the correct values. I believe this is because the pointers are passed by value, so the update at the end of the function has no effect. How should I change my code to achieve the desired effect?
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
void esort(double* lambda, double* vecs, int* n) {
double* res_lam = new double[*n];
double* res_vec = new double[*n * *n];
vector<pair<double, int> > order(*n);
for (int i=0; i<*n; i++) {
order[i] = make_pair(lambda[i], i);
}
sort(order.rbegin(), order.rend());
for (int i=0; i<*n; i++) {
pair<double, int> p = order.at(i);
res_lam[i] = p.first;
for (int j=0; j<*n; j++) {
res_vec[*n*i + j] = vecs[*n*p.second + j];
}
}
lambda = res_lam;
vecs = res_vec;
delete [] res_lam;
delete [] res_vec;
return;
}
int main() {
double lambda[] = {0.5, 2.0, 1.0};
double vecs[] = {0.5, 0.5, 0.5, 2.0, 2.0, 2.0, 1.0, 1.0, 1.0};
int n = 3;
esort(lambda, vecs, &n);
cout << "lambda" << endl;
for (int i=0; i<n; i++) {
cout << lambda[i] << " ";
}
cout << endl;
cout << "vecs" << endl;
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
cout << vecs[j*n + i] << " ";
}
cout << endl;
}
return 0;
}
Output:
lambda
0.5 2 1
vecs
0.5 2 1
0.5 2 1
0.5 2 1
Desired Output:
lambda
0.5 1 2
vecs
0.5 1 2
0.5 1 2
0.5 1 2
EDIT: The ith element of lambda
corresponds to the ith column of vecs
(in Fortran's column-major order). In order to avoid hassling with multi-dimensional arrays in C++, I am simply representing vecs
as a 1D array within esort
. The point of esort
is to sort lambda
and then reorder vecs
such that the ith element of lambda
still corresponds to the ith column of vecs
.
EDIT 2: By placing cout
statements inside esort
, I have confirmed that res_lam
and res_vec
have the values that I want them to have at the end of the routine. My issue is getting those values returned to the calling program.
It is true that C++ passes all of its arguments by value, including pointers, meaning that assigning to
lambda
andvecs
has no effect on the caller: those variables only point to the data. You need to copy your results into that pointed-to memory, as shown below by usingcopy
from<algorithm>
. Alsorbegin
andrend
are reverse iterators, which causessort
to sort backward from what you wanted; I changed it tobegin
andend
. I would further suggest usingvector
for your temporaryres_lam
andres_vec
arrays.