How use arrays of double[4][4] contained in a vector? - c++

I want to ask at the community my problem.
I have a series of array of double[4][4] in this format:
double T1[4][4] = {
{-0.9827, -0.1811, -0.0388, 0.1234},
{0.0807, -0.2303, -0.9698, 0.1755},
{0.1666, -0.9561, 0.2409, 0.6729},
{0, 0, 0, 1.00000 }};
double T2[4][4] = {
{-0.8524, -0.5029, -0.1432, 0.1963},
{0.1580, 0.0135, -0.9874, 0.1285},
{0.4984, -0.8643, 0.0680, 0.6237},
{0, 0, 0, 1.00000 }};
T3, T4, and so on....
I need to insert all of these arrays in a container, to pickup one at time from another function, that need arrays in that format, because doing these elaborations:
int verifica_punti(punto P, Mat& I, double TC[4][4], const double fc[2],const double KC[5], const double cc[2],const double alpha){
//punto
double P1[4] = {P.x, P.y, P.z, 1.0};
//iniz
double Pc[3] = {TC[0][3], TC[1][3], TC[2][3]};
//calc
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
Pc[i] += TC[i][j] * P1[j];
}
}
//norm
double PN[2] = { Pc[0]/Pc[2], Pc[1]/Pc[2] };
Now, searching on this site and on internet I've found some examples to do this, but don't work in my case. Using vector, array, queue...I don't understand a thing.
I paste here my code, and tell you to help me fix this problem.
This is my code:
//array of TC
typedef array<array<double,4>,4> Matrix;
//single TC
Matrix T1 = {{
{{-1.0000, 0.0000, -0.0000, 0.1531}},
{{0.0000, 0.0000, -1.0000, 0.1502 }},
{{-0.0000, -1.0000, -0.0000, 1.0790}},
{{0 , 0, 0, 1.0000 }}}};
Matrix T2 = {{
{{-1.0000, 0.0009, 0.0019, 0.1500}},
{{-0.0021, -0.4464, -0.8948, 0.1845}},
{{0.0000, -0.8948, 0.4464, 0.8094 }},
{{ 0, 0, 0, 1.0000 }}}};
etc....then, declare container and fill it:
vector <Matrix> TCS;
TCS.push_back(T1);
TCS.push_back(T2);
TCS.push_back(T3);
TCS.push_back(T4);
TCS.push_back(T5);
TCS.push_back(T6);
TCS.push_back(T7);
TCS.push_back(T8);
TCS.push_back(T9);
Now, for obtain single matrix in double[4][4] format to pass it at that function "verifica_punti" (written before) how can I do?
I need one TC at time, but in the FIFO order (the first that I've pushed, I need to pop and use.
How can I do this? Because I've write
double temp[4][4] = TCS.pop_back()
or double temp[4][4] = TCS[i];
but isn't correct.
I'm on Visual C++ 2010 on windows 7 64bit.
Help me please :-( thanks in advance.

with
typedef array<array<double,4>,4> Matrix;
vector <Matrix> TCS;
You have
//double temp[4][4] = TCS[i]; // Illegal
Matrix m1 = TCS[i]; // legal
const Matrix& m2 = TCS[i]; // legal, and avoid a copy.
Now, you have to change:
int verifica_punti(punto P, Mat& I, double TC[][4], const double fc[], const double KC[], const double cc[], const double alpha);
to
int verifica_punti(punto P, Mat& I, Matrix& TC, const double fc[], const double KC[], const double cc[], const double alpha);

std::array< std::array<double,4>, 4> and double[4][4] are distinct types. The former encupsulates the latter so that it's copyable and can be used in containers and it has practicaly identical interface. But you can't use them interchangeable.
You already have your typedef, so use that:
while (!TCS.empty()) {
// get the last one
Matrix m = TCS.back();
/* do stuff with m */
// pop the last one out
TCS.pop_back();
}

Related

Assigning pre-allocated array to pointer in class constructor C++

I am working on a project for my advanced CFD class, in which we have to solve the heat equation over a curvilinear mesh. I am trying to create an object which will store all of my data, to allow me to visualize it easily later on. This object is created using a class called Solution. Solution contains 8 public variables, all of which are double precision, *x, *y, *u, *v, *T, nx, ny and N, where x and y store the coordinates for each point, u and v the velocities for each point, T stores the temperature for each point, nx and ny store the number of grid points in the x and y direction, and finally N stores the total number of grid points. I have 3 constructors, the first of which initializes the object with all null pointers or values of 0.
Solution::Solution() : X(nullptr), Y(nullptr), u(nullptr), v(nullptr), T(nullptr), nx(0), ny(0), N(0)
The second constructor takes a value for nx and ny, calculates the number of points, allocates memory for each of the arrays, and initializes their values to 0.
// Constructor to initialize solution struct with 0 values
Solution::Solution(unsigned long iNx, unsigned long iNy) : X(nullptr), Y(nullptr), u(nullptr), v(nullptr), T(nullptr), nx(iNx), ny(iNy)
{
N = nx * ny; // Total number of grid points
// Allocate memory for solution variables
O.alloc1D(&X, N);
O.alloc1D(&Y, N);
O.alloc1D(&u, N);
O.alloc1D(&v, N);
O.alloc1D(&T, N);
// Initialize variables values to 0
for(int i = 0; i < N; i++)
{
X[i] = 0.0;
Y[i] = 0.0;
u[i] = 0.0;
v[i] = 0.0;
T[i] = 0.0;
}
}
Where I am having trouble is for my 3rd constructor, in which I hope to create the object using pre-defined arrays.
// Constructor to initialize solution struct using vectors that already exist
Solution::Solution(unsigned long iNx, unsigned long iNy, double *iX, double *iY, double *iu, double *iv, double *iT) :
X(iX), Y(iY), u(iu), v(iv), T(iT), nx(iNx), ny(iNy)
I am having issues figuring out how to assign the arrays to these values. Looking at just X, if I try to implement an array
double x[4] = {1.0, 2.0, 3.0, 4.0};
for X in the constructor it gives me an error as it cannot assign a double to double*. If I try to write
double *x[4] = {1.0, 2.0, 3.0, 4.0};
it gives me an error as it cannot assign double to double* for each value in the array. If I try
double *x;
double x1[4] = {1, 2, 3, 4};
x = &x1;
it gives me an error because it cannot convert double(*)[4] to double in initialization. I feel like there is an easy solution to let me construct my Solution object with arrays that are already defined, but I'm getting stuck. Thank you for your help.

pass parameters of double but get Jet<double,6>when using ceres solver

I'm a new learner to Ceres Solver, when adding the residualblock using
problem.AddResidualBlock( new ceres::AutoDiffCostFunction<Opt, 1, 6> (new Opt(Pts[i][j].x, Pts[i][j].y, Pts[i][j].z, Ns[i].at<double>(0, 0), Ns[i].at<double>(1, 0), Ns[i].at<double>(2, 0), Ds[i], weights[i]) ),
NULL,
param );
where param is double[6];
struct Opt
{
const double ptX, ptY, ptZ, nsX, nsY, nsZ, ds, w;
Opt( double ptx, double pty, double ptz, double nsx, double nsy, double nsz, double ds1, double w1):
ptX(ptx), ptY(pty), ptZ(ptz), nsX(nsx), nsY(nsy), nsZ(nsz), ds(ds1), w(w1) {}
template<typename T>
bool operator()(const T* const x, T* residual) const
{
Mat R(3, 3, CV_64F), r(1, 3, CV_64F);
Mat inverse(3,3, CV_64F);
T newP[3];
T xyz[3];
for (int i = 0; i < 3; i++){
r.at<T>(i) = T(x[i]);
cout<<x[i]<<endl;
}
Rodrigues(r, R);
inverse = R.inv();
newP[0]=T(ptX)-x[3];
newP[1]=T(ptY)-x[4];
newP[2]=T(ptZ)-x[5];
xyz[0]= inverse.at<T>(0, 0)*newP[0] + inverse.at<T>(0, 1)*newP[1] + inverse.at<T>(0, 2)*newP[2];
xyz[1] = inverse.at<T>(1, 0)*newP[0] + inverse.at<T>(1, 1)*newP[1] + inverse.at<T>(1, 2)*newP[2];
xyz[2] = inverse.at<T>(2, 0)*newP[0] + inverse.at<T>(2, 1)*newP[1] + inverse.at<T>(2, 2)*newP[2];
T ds1 = T(nsX) * xyz[0] + T(nsY) * xyz[1] + T(nsZ) * xyz[2];
residual[0] = (ds1 - T(ds)) * T(w);
}
};
but when I output the x[0], I got this:
[-1.40926 ; 1, 0, 0, 0, 0, 0]
after I change the type of the x to double
I got this error :
note: no known conversion for argument 1 from ‘const ceres::Jet<double, 6>* const’ to ‘const double*’
in
bool operator()(const double* const x, double* residual) const
what's wrong with my codes?
Thanks a lot!
I am guessing you are using cv::Mat.
The reason the functor is templated is because Ceres evaluates it using doubles when it needs just the residuals, and evaluates with ceres:Jet objects when it needs to compute the Jacobian. So your attempt to fill r as
for (int i = 0; i < 3; i++){
r.at<T>(i) = T(x[i]);
cout<<x[i]<<endl;
}
are trying to convert a Jet into a double. Which is what the compiler is correctly complaining about.
you can re-write your code as (I have not compiled it, so there maybe a minor typo or two).
template<typename T>
bool operator()(const T* const x, T* residual) const {
const T inverse_rotation[3] = {-x[0], -x[1], -x[3]};
const T newP[3] = {ptX - x[3], ptY - x[4]. ptZ - x[5]};
T xyz[3];
ceres::AngleAxisRotatePoint(inverse_rotation, newP, xyz);
const T ds1 = nsX * xyz[0] + nsY * xyz[1] + nsZ * xyz[2];
residual[0] = (ds1 - ds) * w;
return true;
}
The automatic derivatives (AutoDiff) needs a templated cost function to keep track of the operations.
Please take a look at the ceres documentation (http://ceres-solver.org/nnls_modeling.html#autodiffcostfunction). There are a lot of nice examples too. I used them as starting point for my first ceres experiments.
I'm not sure if you can use ceres cost functions with OpenCV functions. In most cases Eigen is used to make the cost function.
Ceres comes with a lot of "ready-to-use" components for cost functions like yours.

How to solve a state space model with Odeint?

I am trying to implement a numerical simulation of a state space model using Eigen and Odeint. My trouble is that I need to reference control data U (predefined before integration) in order to properly solve the Ax+Bu part of the state space model. I was trying to accomplish this by using a counter to keep track of the current time step, but for whatever reason, it is reset to zero every time the System Function is called by Odeint.
How would I get around this? Is my approach to modeling the state space system flawed?
My System
struct Eigen_SS_NLTIV_Model
{
Eigen_SS_NLTIV_Model(matrixXd &ssA, matrixXd &ssB, matrixXd &ssC,
matrixXd &ssD, matrixXd &ssU, matrixXd &ssY)
:A(ssA), B(ssB), C(ssC), D(ssD), U(ssU), Y(ssY)
{
Y.resizeLike(U);
Y.setZero();
observerStep = 0;
testPtr = &observerStep;
}
/* Observer Function:*/
void operator()(matrixXd &x, double t)
{
Y.col(observerStep) = C*x + D*U.col(observerStep);
observerStep += 1;
}
/* System Function:
* ONLY the mathematical description of the system dynamics may be placed
* here. Any data placed in here is destroyed after each iteration of the
* stepper.
*/
void operator()(matrixXd &x, matrixXd &dxdt, double t)
{
dxdt = A*x + B*U.col(*testPtr);
//Cannot reference the variable "observerStep" directly as it gets reset
//every time this is called. *testPtr doesn't work either.
}
int observerStep;
int *testPtr;
matrixXd &A, &B, &C, &D, &U, &Y; //Input Vectors
};
My ODE Solver Setup
const double t_end = 3.0;
const double dt = 0.5;
int steps = (int)std::ceil(t_end / dt) + 1;
matrixXd A(2, 2), B(2, 2), C(2, 2), D(2, 2), x(2, 1);
matrixXd U = matrixXd::Constant(2, steps, 1.0);
matrixXd Y;
A << -0.5572, -0.7814, 0.7814, 0.0000;
B << 1.0, -1.0, 0.0, 2.0;
C << 1.9691, 6.4493, 1.9691, 6.4493;
D << 0.0, 0.0, 0.0, 0.0;
x << 0, 0;
Eigen_SS_NLTIV_Model matrixTest(A, B, C, D, U, Y);
odeint::integrate_const(odeint::runge_kutta4<matrixXd, double, matrixXd, double,
odeint::vector_space_algebra>(),
matrixTest, x, 0.0, t_end, dt, matrixTest);
//Ignore these two functions. They are there mostly for debugging.
writeCSV<matrixXd>(Y, "Y_OUT.csv");
prettyPrint<matrixXd>(Y, "Out Full");
With classical Runge-Kutta you know that your ODE model function is called 4 times per step with times t, t+h/2, t+h/2, t+h. With other solvers that implement adaptive step size you can not know in advance at what t the ODE model function is called.
You should implement U via some kind of interpolation function, in the most simple case as step function that computes some index from t and returns the U value for that index. Something like
i = (int)(t/U_step)
dxdt = A*x + B*U.col(i);

Returning double * in function argument

Countless GSL functions return their result as a pointer in their first argument. For instance
int gsl_matrix_get_col (gsl_vector * v, const gsl_matrix * m, size_t j)
My programming level is very low, but I was told such things were impossible with local variables (deleted on end of function), but possible with pointers, as long as they were declared and allocated correctly by the caller function. I find it very strange, such fundamental difference should exist between pointers and normal variables, but I tried to use this storing of results in variables for a simple GSL programme, where I want a function (fetch_eigenvalue()) to output two things. And I fail. My programme is the following:
#include <math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
/* Parameters */
#define N 3
int CREATE_MATRIX_AND_VECTOR(gsl_matrix *m, gsl_vector *v);
double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos);
int main()
{
gsl_matrix *unit_matrix = gsl_matrix_calloc(N, N); //soon to be unity
gsl_vector *v = gsl_vector_calloc(N); //soon to be unit x vector
double *outcos = (double*)malloc(sizeof(double) );
printf("**********************************************\n");
CREATE_MATRIX_AND_VECTOR(unit_matrix, v);
fetch_eigenvalue(unit_matrix, v, outcos);
printf("==IN MAIN: outcos = %e\n", *outcos);
free((void *)outcos);
gsl_vector_free(v);
gsl_matrix_free(unit_matrix);
printf("**********************************************\n");
return(0);
}
int CREATE_MATRIX_AND_VECTOR(gsl_matrix * m, gsl_vector *v)
{
int i;
for (i = 0; i < N; i++)
{
gsl_matrix_set(m, i, i, 1.0);
}
gsl_vector_set(v, 0, 1.0);
return(0);
}
double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos) //fetches eigenvalue, if Mv is parallel to v within accuracy gvaccu
//rescos is the cosine of the angle between Mv and v
{
int i,lv;
double v0, v1, cos;
double result;
double vnorm, pnorm;
double rdot;
lv = v->size;
double gvaccu = 1e-10;
gsl_vector *prod = gsl_vector_calloc(lv);
gsl_matrix_get_row(prod, M, 0);
if(gsl_blas_dnrm2(prod)==0.0)
{
result = 0.0;
}
else
{
gsl_blas_dgemv( CblasNoTrans,1.0, M, v, 0.0, prod);
gsl_blas_ddot(prod, v, &rdot);
pnorm = gsl_blas_dnrm2(prod);
vnorm = gsl_blas_dnrm2(v);
cos = rdot/pnorm/vnorm;
cos = fabs(cos);
rescos = &cos;
if(fabs(cos -1.0) > gvaccu)
{
result = -1.0;
}
else
{
v0 = gsl_vector_get(v,0);
v1 = gsl_vector_get(prod,0);
result = v1/v0;
}
}
printf("==IN FETCH_EV: COS = %e\n", cos);//print cheat!!
printf("==IN FETCH_EV: RESCOS = %e\n", *rescos);//print cheat!!
gsl_vector_free(prod);
return(result);
}
I run it and get the following output:
ludi#ludi-M17xR4:~/Desktop/Healpix_3.20$ g++ -o wrong_output wrong_output.c -L. -L/sw/lib -I/sw/include -lgsl -lblas && ./wrong_output
**********************************************
==IN FETCH_EV: COS = 1.000000e+00
==IN FETCH_EV: RESCOS = 1.000000e+00
==IN MAIN: outcos = 0.000000e+00
**********************************************
ludi#ludi-M17xR4:~/Desktop/Healpix_3.20$
So, the caller main() knows nothing about what happened inside fetch_eigenvalue(), eventhough I used a pointer. What am I doing wrong? I have the feeling, that I have misunderstood something very essential.
I sum up what you do with the parameter rescos in your fetch_eigenvalue function:
double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos)
{
double cos;
// some code
rescos = &cos;
// some code
return(result);
}
Here you're not modifying the double value pointed by rescos, you're modifying the varaible rescos itself, which is a copy of the variable outcos used in your main.
What you want to do in fetch_eigenvalue is copying the value of cos into the variable pointed by rescos:
double fetch_eigenvalue(gsl_matrix *M, gsl_vector *v, double *rescos)
{
double cos;
// some code
*rescos = cos;
// some code
return(result);
}
EDIT: As stated by the other answers, it's better to avoid malloc when you can, and here you can:
double outcos;
fetch_eigenvalue(unit_matrix, v, &outcos);
I suspect that this is because the statement rescos = &cos; saves into rescos the address of the local variable cos. However, the scope of this variable is only local so that you can not then use it in the main(). I guess what you want to do is to:
change rescos = &cos; to *rescos = cos; in the fetch_eigenvalue function so that the value of cos is stored at the address pointed to by rescos
use merely double outcos; in the main() function, i.e., don't use pointer
call fetch_eigenvalue as fetch_eigenvalue(unit_matrix, v, &outcos);
I don't know anything about GSL, but it appears to be a library that uses C-style interface. To set values from a function, they use pointers. You don't seem to know how to use such an API yet, so here's some hints.
The statements
double *outcos = (double*)malloc(sizeof(double) );
...
fetch_eigenvalue(unit_matrix, v, outcos);
is not how you want to use such an API. Instead, you just define a double variable, and use the address of operator in the call:
double outcos;
...
fetch_eigenvalue(unit_matrix, v, &outcos);
Also, in your method, to assign a value, use don't use
cos = fabs(cos);
rescos = &cos;
but
cos = fabs(cos);
*rescos = cos;
to assign the value to the variable pointed to, not to the pointer.
Hope this helps.

Tensor Product Algorithm Optimization

double data[12] = {1, z, z^2, z^3, 1, y, y^2, y^3, 1, x, x^2, x^3};
double result[64] = {1, z, z^2, z^3, y, zy, (z^2)y, (z^3)y, y^2, z(y^2), (z^2)(y^2), (z^3)(y^2), y^3, z(y^3), (z^2)(y^3), (z^3)(y^3), x, zx, (z^2)x, (z^3)x, yx, zyx, (z^2)yx, (z^3)yx, (y^2)x, z(y^2)x, (z^2)(y^2)x, (z^3)(y^2)x, (y^3)x, z(y^3)x, (z^2)(y^3)x, (z^3)(y^3)x, x^2, z(x^2), (z^2)(x^2), (z^3)(x^2), y(x^2), zy(x^2), (z^2)y(x^2), (z^3)y(x^2), (y^2)(x^2), z(y^2)(x^2), (z^2)(y^2)(x^2), (z^3)(y^2)(x^2), (y^3)(x^2), z(y^3)(x^2), (z^2)(y^3)(x^2), (z^3)(y^3)(x^2), x^3, z(x^3), (z^2)(x^3), (z^3)(x^3), y(x^3), zy(x^3), (z^2)y(x^3), (z^3)y(x^3), (y^2)(x^3), z(y^2)(x^3), (z^2)(y^2)(x^3), (z^3)(y^2)(x^3), (y^3)(x^3), z(y^3)(x^3), (z^2)(y^3)(x^3), (z^3)(y^3)(x^3)};
What is the fastest (fewest executions) to produce result given data? Assume, that data is variable in size, but always a factor of 4 (e.g., 4, 8, 12, etc.).
No Boost. I am trying to keep my dependencies small. STL Algorithms are ok.
HINT: result array size should always be 4^(multiple size) (e.g., 4, 16, 64, etc.).
BONUS: If you can compute result just given x, y, z
Additional examples:
double data[4] = {1, z, z^2, z^3};
double result[4] = {1, z, z^2, z^3};
double data[8] = {1, z, z^2, z^3, 1, y, y^2, y^3};
double result[16] = { ... };
I chose the accepted answer code after running this benchmark: https://gist.github.com/1232406. Basically, the top two codes were run and the one with the smallest execution time won.
void Tensor(std::vector<double>& result, double x, double y, double z) {
result.resize(64); //almost noop if already right size
double tz = z*z;
double ty = y*y;
double tx = x*x;
std::array<double, 12> data = {0, 0, tz, tz*z, 1, y, ty, ty*y, 1, x, tx, tx*x};
register std::vector<double>::iterator iter = result.begin();
register int yi;
register double xy;
for(register int xi=0; xi<4; ++xi) {
for(yi=0; yi<4; ++yi) {
xy = data[4+yi]*data[8+xi];
*iter = xy; //a smart compiler can do these four in parallell
*(++iter) = z*xy;
*(++iter) = data[2]*xy;
*(++iter) = data[3]*xy;
++iter; //workaround for speed!
}
}
}
There's probably at least one bug in here somewhere, but it should be fast, with no dependancies (outside of std::vector/std::array), just takes x,y,z. I avoided recursion though, so it only works for 3 in/64 out. The concept can be applied to any number of parameters though. You just have to instantiate yourself.
A good compiler will autovectorize this I guess none of my compilers are good:
void tensor(const double *restrict data,
int dimensions,
double *restrict result) {
result[0] = 1.0;
for (int i = 0; i < dimensions; i++) {
for (int j = (1 << (i * 2)) - 1; j > -1; j--) {
double alpha = result[j];
{
double *restrict dst = &result[j * 4];
const double *restrict src = &data[(dimensions - 1 - i) * 4];
for (int k = 0; k < 4; k++) dst[k] = alpha * src[k];
}
}
}
}
you should use dynamic algorithm. that is, you can use previous results. for example, you keep y^2 result and use it when computing (y^2)z instead of computing it again.
#include <vector>
#include <cstddef>
#include <cmath>
void Tensor(std::vector<double>& result, const std::vector<double>& variables, size_t index)
{
double p1 = variables[index];
double p2 = p1*p1;
double p3 = p1*p2;
if (index == variables.size() - 1) {
result.push_back(1);
result.push_back(p1);
result.push_back(p2);
result.push_back(p3);
} else {
Tensor(result, variables, index+1);
ptrdiff_t size = result.size();
for(int j=0; j<size; ++j)
result.push_back(result[j]*p1);
for(int j=0; j<size; ++j)
result.push_back(result[j]*p2);
for(int j=0; j<size; ++j)
result.push_back(result[j]*p3);
}
}
std::vector<double> Tensor(const std::vector<double>& params) {
std::vector<double> result;
double rsize = (1<<(2*params.size());
result.reserve(rsize);
Tensor(result, params);
return result;
}
int main() {
std::vector<double> params;
params.push_back(3.1415926535);
params.push_back(2.7182818284);
params.push_back(42);
params.push_back(65536);
std::vector<double> result = Tensor(params);
}
I verified that this one compiles and runs (http://ideone.com/IU1eQ). It runs fast, with no dependancies (outside of std::vector). It also takes any number of parameters. Since calling the recursive form is awkward, I made a wrapper. It makes one function call for each parameter, and one call to dynamic memory (in the wrapper).
You should look for Pascal's pyramid to get fast solution. Useful link 1, useful link 2, useful link 3 and useful link 4.
One more thing: as I see it would be a base of a finite element solver. Usually to write own BLAS solver is not a good idea. Do not reinvent the wheel! I think you should use a BLAS solver like intel MKL or Cuda base BLAS.