I'm not sure what I went wrong, my code doesn't seem to work with anything else beside single integer. Am trying to get 3x3 array and find its determinant and work out its inverse function and then do the multiplication to get I.
//matrix product
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++) {
product[i][j] += array[i][k] * invertA[k][j];
}
}
}
... Below is the array from user input
int main() {
int array[3][3], invertA[3][3], product[3][3], i, j, k; // The global scope
// ask for input
printf("Please enter 9 elements of the matrix seperated by a space: \n");
for (i = 0; i < 3; i++) { //the loop - create a table of 3 x 3
for (j = 0; j < 3; j++) {
scanf("%d", &array[i][j]); //save user-input as integer (%d) into the matrix a[i][j]
}
}
and the other array is from code
//a11 a12 a13
invertA[0][0] = (array[1][1] * array[2][2] - array[2][1] * array[1][2]) / determinant;
invertA[0][1] = -(array[1][0] * array[2][2] - array[1][2] * array[2][0]) / determinant;
invertA[0][2] = (array[1][0] * array[2][1] - array[2][0] * array[1][1]) / determinant;
//a21 a22 a23
invertA[1][0] = -(array[0][1] * array[2][2] - array[0][2] * array[2][1]) / determinant;
invertA[1][1] = (array[0][0] * array[2][2] - array[0][2] * array[2][0]) / determinant;
invertA[1][2] = -(array[0][0] * array[2][1] - array[2][0] * array[0][1]) / determinant;
//a31 a32 a33
invertA[2][0] = (array[0][1] * array[1][2] - array[0][2] * array[1][1]) / determinant;
invertA[2][1] = -(array[0][0] * array[1][2] - array[1][0] * array[0][2]) / determinant;
invertA[2][2] = (array[0][0] * array[1][1] - array[1][0] * array[0][1]) / determinant;
Related
I have been trying to port a code for an university-related project from C to C++ while also adapting it to an object-oriented paradigm. The original code makes use of OpenMP, through pragmas to create a parallel variation of a function used to calculate certain values and matrices according to an input given by the user.
In C, I wrote a function that returns a struct data type I have defined myself like such. A note: the DoubVet1D/2D functions basically call calloc to initialize arrays of a size defined by their argument(s).
SaidaEstacionario getDDParallel(DadosEntrada e){
SaidaEstacionario dd;
/*
* Preenche os vetores com os dados do dom�nio
*/
int J = 0;
for (int i = 0; i < e.numReg; i++)
J += e.partReg[i];
int N = e.ordQuad;
dd.dimFi = J + 1;
//NNR = e.NNR;
//double Stop = e.erro;
//TipoContorno = e.CCETipo + e.CCDTipo;
double *St = DoubVet1D(J);
double *Ss = DoubVet1D(J);
double *Q = DoubVet1D(J);
double *h = DoubVet1D(J);
double *S = DoubVet1D(J);
//double *Fi = DoubVet1D(J + 1);
//double *x = DoubVet1D(J + 1);
//double *TaxaAbR = DoubVet1D(e.numReg);
double **psiOld = DoubVet2D(e.ordQuad, J + 1);
double **psi = DoubVet2D(e.ordQuad, J + 1);
double tmpErro = 0;
double erro = 0;
int k = 0;
dd.fi = DoubVet1D(J + 1);
dd.x = DoubVet1D(J + 1);
dd.x[0] = 0;
for (int i = 0; i < e.numReg; i++)
{
double temp = e.tamReg[i] / e.partReg[i];
for (int j = 0; j < e.partReg[i]; j++)
{
h[k] = temp;
Ss[k] = e.ssZon[e.zonReg[i]];
St[k] = e.stZon[e.zonReg[i]];
Q[k] = e.fontReg[i];
dd.x[k + 1] = dd.x[k] + temp;
k++;
}
}
/* Estabelecendo a condi��o de contorno */
for (int n = 0; n < e.ordQuad/2; n++)
{
if(e.cce < 0){
psi[n][0] = 0;
psiOld[n][0] = psi[n][0];
}
else{
psi[n][0] = e.cce;
psiOld[n][0] = psi[n][0];
}
if(e.ccd < 0){
psi[e.ordQuad/2 + n][J] = 0;
psiOld[e.ordQuad/2 + n][0] = psi[e.ordQuad/2 + n][0];
}
else{
psi[e.ordQuad/2 + n][J] = e.ccd;
psiOld[e.ordQuad/2 + n][0] = psi[e.ordQuad/2 + n][0];
}
}
/* Obtendo as quadraturas de Gauss-Legendre */
PLegendre pl = GaussLegendreAbsPes(e.ordQuad);
double *Mi = pl.mi;
double *W = pl.w;
//#############################################
double start;
dd.numInter = 0;
do{
dd.numInter++;
/* Calculando a fonte de espalhamento */
#pragma omp parallel for
for (int j = 0; j < J; j++)
{
S[j] = 0;
for (int n = 0; n < N; n++)
S[j] += 0.25 * Ss[j] * (psi[n][j + 1] + psi[n][j]) * W[n];
}
/* Varredura para a direita/esquerda */
#pragma omp sections
{
#pragma omp section
{
#pragma omp parallel for
for (int m = 0; m < N / 2; m++)
for (int j = 0; j < J; j++)
{
/* Varredura para a direita */
psiOld[m][j + 1] = psi[m][j + 1];
psi[m][j + 1] = ((Mi[m] / h[j] - 0.5 * St[j]) * psi[m][j] + S[j] + Q[j]) / (Mi[m] / h[j] + 0.5 * St[j]);
}
}
#pragma omp section
{
#pragma omp parallel for
for (int m = 0; m < N / 2; m++)
for (int j = 0; j < J; j++)
{
/* Varredura para a esquerda */
psiOld[m + N / 2][J - 1 - j] = psi[m + N / 2][J - 1 - j];
psi[m + N / 2][J - 1 - j] = ((Mi[m] / h[J - 1 - j] - 0.5 * St[J - 1 - j]) * psi[m + N / 2][J - j] + S[J - 1 - j] + Q[J - 1 - j]) / (Mi[m] / h[J - 1 - j] + 0.5 * St[J - 1 - j]);
}
}
} // Aqui h� uma barreira impl�cita
/* Estabelecendo a condi��o de contorno */
if(e.cce < 0 || e.ccd < 0){
#pragma omp parallel for
for (int n = 0; n < e.ordQuad/2; n++)
{
if(e.cce < 0){
psiOld[n][0] = psi[n][0];
psi[n][0] = psi[e.ordQuad/2 + n][ 0];
}
if(e.ccd < 0){
psiOld[e.ordQuad/2 + n][0] = psi[n][0];
psi[e.ordQuad/2 + n][J] = psi[n][J];
}
}
}
/* Calculando o erro para o crit�rio de parada*/
tmpErro = 0;
erro = 0;
for (int m = 0; m < N; m++)
for (int j = 0; j < J; j++){
tmpErro = Abs(psi[m][j] - psiOld[m][j])/psi[m][j];
if(tmpErro > erro) erro = tmpErro;
}
}while(erro > e.erro);
dd.tempoVar = omp_get_wtime() - start;
dd.psi = DoubVet2D(e.ordQuad, J + 1);
/* Calcula o fluxo escalar */
#pragma omp parallel for
for (int j = 0; j <= J; j++){
dd.fi[j] = 0;
for (int m = 0; m < N; m++){
dd.fi[j] += psi[m][j] * W[m];
dd.psi[m][j] = psi[m][j];
}
}
/*Calcula a taxa de absorção*/
int i = 0;
dd.taxaAbsorRegiao = DoubVet1D(e.numReg);
dd.taxaAbsorTotal = 0;
for (int r = 0; r < e.numReg; r++)
{
dd.taxaAbsorRegiao[r] = 0;
#pragma omp parallel for
for (int j = i; j < i + e.partReg[r]; j++)
dd.taxaAbsorRegiao[r] += 0.5 * (dd.fi[j] + dd.fi[j + 1]);
dd.taxaAbsorRegiao[r] *= (St[i] - Ss[i]) * h[i];
dd.taxaAbsorTotal += dd.taxaAbsorRegiao[r];
i += e.partReg[r];
}
return dd;
}
///Execu��o dos c�lculos do m�todo Diamod Difference DD ou Dg estacion�rio vers�o parallel
SaidaEstacionario getDgDDParallel(DadosEntrada e){
SaidaEstacionario saida;
/*
* Preenche os vetores com os dados do dom�nio
*/
int J = 0;
for (int i = 0; i < e.numReg; i++)
J += e.partReg[i];
int N = e.ordQuad;
saida.dimFi = J + 1;
//NNR = e.NNR;
//double Stop = e.erro;
//TipoContorno = e.CCETipo + e.CCDTipo;
double *St = DoubVet1D(J);
double *Ss = DoubVet1D(J);
double *Q = DoubVet1D(J);
double *h = DoubVet1D(J);
double *S = DoubVet1D(J);
//double *Fi = DoubVet1D(J + 1);
//double *x = DoubVet1D(J + 1);
//double *TaxaAbR = DoubVet1D(e.numReg);
double **psiOld = DoubVet2D(e.ordQuad, J + 1);
double **psi = DoubVet2D(e.ordQuad, J + 1);
double tmpErro = 0;
double erro = 0;
int k = 0;
saida.fi = DoubVet1D(J + 1);
saida.x = DoubVet1D(J + 1);
saida.x[0] = 0;
for (int i = 0; i < e.numReg; i++)
{
double temp = e.tamReg[i] / e.partReg[i];
for (int j = 0; j < e.partReg[i]; j++)
{
h[k] = temp;
Ss[k] = e.ssZon[e.zonReg[i]];
St[k] = e.stZon[e.zonReg[i]];
Q[k] = e.fontReg[i];
saida.x[k + 1] = saida.x[k] + temp;
k++;
}
}
/* Estabelecendo a condi��o de contorno */
for (int n = 0; n < e.ordQuad/2; n++)
{
if(e.cce < 0){
psi[n][0] = 0;
psiOld[n][0] = psi[n][0];
}
else{
psi[n][0] = e.cce;
psiOld[n][0] = psi[n][0];
}
if(e.ccd < 0){
psi[e.ordQuad/2 + n][J] = 0;
psiOld[e.ordQuad/2 + n][0] = psi[e.ordQuad/2 + n][0];
}
else{
psi[e.ordQuad/2 + n][J] = e.ccd;
psiOld[e.ordQuad/2 + n][0] = psi[e.ordQuad/2 + n][0];
}
}
/* Obtendo as quadraturas de Gauss-Legendre */
PLegendre pl = GaussLegendreAbsPes(e.ordQuad);
double *Mi = pl.mi;
double *W = pl.w;
//#############################################
double start;
start = omp_get_wtime();
saida.numInter = 0;
do{
saida.numInter++;
/* Calculando a fonte de espalhamento */
#pragma omp parallel for
for (int j = 0; j < J; j++)
{
S[j] = 0;
for (int n = 0; n < N; n++)
S[j] += 0.25 * Ss[j] * (psi[n][j + 1] + psi[n][j]) * W[n];
}
/* Varredura para a direita/esquerda */
#pragma omp sections
{
#pragma omp section
{
#pragma omp parallel for
for (int m = 0; m < N / 2; m++)
for (int j = 0; j < J; j++)
{
/* Varredura para a direita */
psiOld[m][j + 1] = psi[m][j + 1];
psi[m][j + 1] = ((Mi[m] / h[j] - 0.5 * St[j] * (1 - e.teta)) * psi[m][j] + S[j] + Q[j]) / (Mi[m] / h[j] + 0.5 * St[j] * (1 + e.teta));
}
}
#pragma omp section
{
#pragma omp parallel for
for (int m = 0; m < N / 2; m++)
for (int j = 0; j < J; j++)
{
/* Varredura para a esquerda */
psiOld[m + N / 2][J - 1 - j] = psi[m + N / 2][J - 1 - j];
psi[m + N / 2][J - 1 - j] = ((Mi[m] / h[J - 1 - j] - 0.5 * St[J - 1 - j] * (1 - e.teta)) * psi[m + N / 2][J - j] + S[J - 1 - j] + Q[J - 1 - j]) / (Mi[m] / h[J - 1 - j] + 0.5 * St[J - 1 - j] * (1 + e.teta));
}
}
} // Aqui h� uma barreira impl�cita
/* Estabelecendo a condi��o de contorno */
if(e.cce < 0 || e.ccd < 0){
#pragma omp parallel for
for (int n = 0; n < e.ordQuad/2; n++)
{
if(e.cce < 0){
psiOld[n][0] = psi[n][0];
psi[n][0] = psi[e.ordQuad/2 + n][ 0];
}
if(e.ccd < 0){
psiOld[e.ordQuad/2 + n][0] = psi[n][0];
psi[e.ordQuad/2 + n][J] = psi[n][J];
}
}
}
/* Calculando o erro para o crit�rio de parada*/
tmpErro = 0;
erro = 0;
for (int m = 0; m < N; m++)
for (int j = 0; j < J; j++){
tmpErro = Abs(psi[m][j] - psiOld[m][j])/psi[m][j];
if(tmpErro > erro) erro = tmpErro;
}
}while(erro > e.erro);
saida.tempoVar = omp_get_wtime() - start;
saida.psi = DoubVet2D(e.ordQuad, J + 1);
/* Calcula o fluxo escalar */
#pragma omp parallel for
for (int j = 0; j <= J; j++){
saida.fi[j] = 0;
for (int m = 0; m < N; m++){
saida.fi[j] += psi[m][j] * W[m];
saida.psi[m][j] = psi[m][j];
}
}
/*Calcula a taxa de absorção*/
int i = 0;
saida.taxaAbsorRegiao = DoubVet1D(e.numReg);
saida.taxaAbsorTotal = 0;
for (int r = 0; r < e.numReg; r++)
{
saida.taxaAbsorRegiao[r] = 0;
#pragma omp parallel for
for (int j = i; j < i + e.partReg[r]; j++)
saida.taxaAbsorRegiao[r] += 0.5 * (saida.fi[j] + saida.fi[j + 1]);
saida.taxaAbsorRegiao[r] *= (St[i] - Ss[i]) * h[i];
saida.taxaAbsorTotal += saida.taxaAbsorRegiao[r];
i += e.partReg[r];
}
return saida;
}
As you can see, I only use #pragma omp parallel for and #pragma omp parallel section. In C++, as part of the object orientation, I transformed the original SaidaEstacionario struct in two classes called Methodand StationaryMethod (which inherits from Method), and implemented the function above as a method of a subclass at the lower end of the inheritance, while also encapsulating the variables and creating getters/setters. The end result was a StationaryMethodclass, which inherits from StationaryMethod, with the following method:
void StationaryDD::calculateParallel(){
/*
* Preenche os vetores com os dados do dom�nio
*/
int J = 0;
for (int i = 0; i < this->inputData.getNumReg(); i++)
J += this->inputData.getPartReg()[i];
int N = this->inputData.getQuadOrder();
this->dimFi = J + 1;
//NNR = this->inputData.NNR;
//double Stop = this->inputData.erro;
//TipoContorno = this->inputData.getCcl()Tipo + this->inputData.getCcr()Tipo;
double *St = DoubVet1D(J);
double *Ss = DoubVet1D(J);
double *Q = DoubVet1D(J);
double *h = DoubVet1D(J);
double *S = DoubVet1D(J);
//double *Fi = DoubVet1D(J + 1);
//double *x = DoubVet1D(J + 1);
//double *TaxaAbR = DoubVet1D(this->inputData.numReg);
double **psiOld = DoubVet2D(this->inputData.getQuadOrder(), J + 1);
double **psi = DoubVet2D(this->inputData.getQuadOrder(), J + 1);
double tmpErro = 0;
double erro = 0;
int k = 0;
this->fi = DoubVet1D(J + 1);
this->x = DoubVet1D(J + 1);
this->x[0] = 0;
for (int i = 0; i < this->inputData.getNumReg(); i++)
{
double temp = this->inputData.getSizeReg()[i] / this->inputData.getPartReg()[i];
for (int j = 0; j < this->inputData.getPartReg()[i]; j++)
{
h[k] = temp;
Ss[k] = this->inputData.getSsZon()[this->inputData.getZonReg()[i]];
St[k] = this->inputData.getStZon()[this->inputData.getZonReg()[i]];
Q[k] = this->inputData.getSrcReg()[i];
this->x[k + 1] = this->x[k] + temp;
k++;
}
}
/* Estabelecendo a condi��o de contorno */
for (int n = 0; n < this->inputData.getQuadOrder()/2; n++)
{
if(this->inputData.getCcl() < 0){
psi[n][0] = 0;
psiOld[n][0] = psi[n][0];
}
else{
psi[n][0] = this->inputData.getCcl();
psiOld[n][0] = psi[n][0];
}
if(this->inputData.getCcr() < 0){
psi[this->inputData.getQuadOrder()/2 + n][J] = 0;
psiOld[this->inputData.getQuadOrder()/2 + n][0] = psi[this->inputData.getQuadOrder()/2 + n][0];
}
else{
psi[this->inputData.getQuadOrder()/2 + n][J] = this->inputData.getCcr();
psiOld[this->inputData.getQuadOrder()/2 + n][0] = psi[this->inputData.getQuadOrder()/2 + n][0];
}
}
/* Obtendo as quadraturas de Gauss-Legendre */
PLegendre pl = PLegendre(this->inputData.getQuadOrder());
double *Mi = pl.getMi();
double *W = pl.getW();
//#############################################
double start;
this->numIter = 0;
do{
this->numIter++;
/* Calculando a fonte de espalhamento */
#pragma omp parallel for
for (int j = 0; j < J; j++)
{
printf("T%d: j = %d\n", omp_get_thread_num(), j);
S[j] = 0;
for (int n = 0; n < N; n++)
S[j] += 0.25 * Ss[j] * (psi[n][j + 1] + psi[n][j]) * W[n];
}
/* Varredura para a direita/esquerda */
#pragma omp sections
{
#pragma omp section
{
#pragma omp parallel for
for (int m = 0; m < N / 2; m++)
for (int j = 0; j < J; j++)
{
/* Varredura para a direita */
psiOld[m][j + 1] = psi[m][j + 1];
psi[m][j + 1] = ((Mi[m] / h[j] - 0.5 * St[j]) * psi[m][j] + S[j] + Q[j]) / (Mi[m] / h[j] + 0.5 * St[j]);
}
}
#pragma omp section
{
#pragma omp parallel for
for (int m = 0; m < N / 2; m++)
for (int j = 0; j < J; j++)
{
/* Varredura para a esquerda */
psiOld[m + N / 2][J - 1 - j] = psi[m + N / 2][J - 1 - j];
psi[m + N / 2][J - 1 - j] = ((Mi[m] / h[J - 1 - j] - 0.5 * St[J - 1 - j]) * psi[m + N / 2][J - j] + S[J - 1 - j] + Q[J - 1 - j]) / (Mi[m] / h[J - 1 - j] + 0.5 * St[J - 1 - j]);
}
}
} // Aqui h� uma barreira impl�cita
/* Estabelecendo a condi��o de contorno */
if(this->inputData.getCcl() < 0 || this->inputData.getCcr() < 0){
#pragma omp parallel for
for (int n = 0; n < this->inputData.getQuadOrder()/2; n++)
{
if(this->inputData.getCcl() < 0){
psiOld[n][0] = psi[n][0];
psi[n][0] = psi[this->inputData.getQuadOrder()/2 + n][ 0];
}
if(this->inputData.getCcr() < 0){
psiOld[this->inputData.getQuadOrder()/2 + n][0] = psi[n][0];
psi[this->inputData.getQuadOrder()/2 + n][J] = psi[n][J];
}
}
}
/* Calculando o erro para o crit�rio de parada*/
tmpErro = 0;
erro = 0;
for (int m = 0; m < N; m++)
for (int j = 0; j < J; j++){
tmpErro = fabs(psi[m][j] - psiOld[m][j])/psi[m][j];
if(tmpErro > erro) erro = tmpErro;
}
}while(erro > this->inputData.getE());
this->tempoVar = omp_get_wtime() - start;
this->psi = DoubVet2D(this->inputData.getQuadOrder(), J + 1);
/* Calcula o fluxo escalar */
#pragma omp parallel for
for (int j = 0; j <= J; j++){
this->fi[j] = 0;
for (int m = 0; m < N; m++){
this->fi[j] += psi[m][j] * W[m];
this->psi[m][j] = psi[m][j];
}
}
/*Calcula a taxa de absorção*/
int i = 0;
this->taxaAbsorRegiao = DoubVet1D(this->inputData.getNumReg());
this->taxaAbsorTotal = 0;
for (int r = 0; r < this->inputData.getNumReg(); r++)
{
this->taxaAbsorRegiao[r] = 0;
#pragma omp parallel for
for (int j = i; j < i + this->inputData.getPartReg()[r]; j++)
this->taxaAbsorRegiao[r] += 0.5 * (this->fi[j] + this->fi[j + 1]);
this->taxaAbsorRegiao[r] *= (St[i] - Ss[i]) * h[i];
this->taxaAbsorTotal += this->taxaAbsorRegiao[r];
i += this->inputData.getPartReg()[r];
}
}
Which basically does the same as the function above, but instead of returning the struct data type, simply stores all the data in the object itself defined by the class.
However, when comparing the time spent in each method, the method implemented in a C++ class takes a LOT more time than the original C function to execute. It is extremely bad to a point that, where the original C method would result in a fair bit of time saved compared to a non-paralellized variation of the same method (that is, without using OpenMP pragmas), this one will be much worse than it, taking up to a minute to finish a calculation that would be done in a fraction of a second. At first, I thought that the encapsulation could be slowing things down, but simply making everything public and calling the attributes directly instead of getters did not work. Would anyone have any insight as to why this could be happening?
I'm trying to rewrite the main loop in a physics simulation and split the workload between more threads.
It calls dostuff on every unique pair of indices and looks like this:
for (int i = 0; i < n - 1; ++i)
{
for (int j = i + 1; j < n; ++j)
{
dostuff(i, j);
}
}
I came up with two options:
//#1
//sqrt is implemented as binary search on ints, floors the result
for (int x = 0; x < n * (n - 1) / 2; ++x)
{
int i = (1 + sqrt(1 + 8 * x)) / 2;
int j = x - i * (i - 1) / 2;
dostuff(i, j);
}
//#2
for (int x = 0; x < n * n; ++x)
{
int i = x % n;
int j = x / n;
if (i < j)
dostuff(i, j);
}
And for each option, there is corresponding thread loop using shared atomic counter:
//#1
while(int x = counter.fetch_add(1) < n * (n - 1) / 2)
{
int i = (1 + sqrt(1 + 8 * x)) / 2;
int j = x - i * (i - 1) / 2;
dostuff(i, j);
}
//#2
while(int x = counter.fetch_add(1) < n * n)
{
int i = x % n;
int j = x / n;
if (i < j)
dostuff(i, j);
}
My question is, what is the best way to share the workload of the main loop between threads for n < 10^6?
EDIT:
//dostuff
Element& a = elements[i];
Element& b = elements[j];
glm::dvec3 r = b.getPosition() - a.getPosition();
double rv = glm::length(r);
double base = G / (rv * rv);
glm::dvec3 dir = glm::normalize(r);
glm::dvec3 bd = dir * base;
accelerations[i] += bd * b.getMass();
accelerations[j] -= bd * a.getMass();
Your work is a triangle. You want to.divide the triangle into k distinct pieces.
If k is a power of 2 you can do this:
a
a a
b c d
b c d d
Each of those regions are equal in size.
I'm trying to create a class that can procedurally create prisms (or cylinders if the precision is high enough) but only the sides of the 3d model are showing (not the top and bottom). This is using openGL and c++. Not going for efficiency, just modifying a previous class that made a sphere.
#define numSlices 2
Prism::Prism() {
init(3);
}
Prism::Prism(int prec) {
init(prec);
}
float Prism::toRadians(float degrees) { return (degrees * 2.0f * 3.14159f) / 360.0f; }
void Prism::init(int prec) {
prec = (prec < 3) ? 3 : prec;
numVertices = (prec + 1) * (numSlices+1);
numIndices = prec * numSlices * 6;
for (int i = 0; i < numVertices; i++) { vertices.push_back(glm::vec3()); }
for (int i = 0; i < numVertices; i++) { texCoords.push_back(glm::vec2()); }
for (int i = 0; i < numVertices; i++) { normals.push_back(glm::vec3()); }
for (int i = 0; i < numVertices; i++) { tangents.push_back(glm::vec3()); }
for (int i = 0; i < numIndices; i++) { indices.push_back(0); }
// calculate triangle vertices
for (int i = 0; i <= numSlices; i++) {
for (int j = 0; j <= prec; j++) {
float y = i;
float x = -(float)cos(toRadians(j * 360.0f / (float)prec));
float z = (float)sin(toRadians(j * 360.0f / (float)prec));
vertices[i * (prec + 1) + j] = glm::vec3(x, y, z);
texCoords[i * (prec + 1) + j] = glm::vec2(((float)j / prec), ((float)i / numSlices));
}
}
// calculate triangle indices
for (int i = 0; i < numSlices; i++) {
for (int j = 0; j < prec; j++) {
indices[6 * (i * prec + j) + 0] = i * (prec + 1) + j;
indices[6 * (i * prec + j) + 1] = i * (prec + 1) + j + 1;
indices[6 * (i * prec + j) + 2] = (i + 1) * (prec + 1) + j;
indices[6 * (i * prec + j) + 3] = i * (prec + 1) + j + 1;
indices[6 * (i * prec + j) + 4] = (i + 1) * (prec + 1) + j + 1;
indices[6 * (i * prec + j) + 5] = (i + 1) * (prec + 1) + j;
}
}
}
Any tips or solutions that stick closely to the code already written would much appreciated.
To render the top and bottom of the cylinder, you can create a "triangle fan" that starts from a vertex at the center of the top/bottom of the cylinder and creates one triangle for every side.
Adapting your code: (untested, I may have made mistakes against winding order)
int bottom_center = vertices.length(); vertices.push_back(glm::vec3(0,0,0));
int top_center = vertices.length(); vertices.push_back(glm::vec3(0,numSlices,0));
// Bottom
for (int j = 0; j < prec; j++) {
int base = 0;
indices.push_back(bottom_center);
indices.push_back(base+j);
indices.push_back(base+j+1);
}
// Top
for (int j = 0; j < prec; j++) {
int base = numSlices * (prec+1);
indices.push_back(top_center);
indices.push_back(base+j);
indices.push_back(base+j+1);
}
See http://www.songho.ca/opengl/gl_cylinder.html for a more worked-out example.
I originally had 3 equations: Pu, Pm & Pd. It ran fine.
Once I introduced the if statement, with variations on the 3 equations, depending on the loop iteration, I receive a runtime error.
Any help would be appreciated.
Cheers in advance.
#include <cmath>
#include <iostream>
#include <vector>
#include <iomanip>
int Rounding(double x)
{
int Integer = (int)x;
double Decimal = x - Integer;
if (Decimal > 0.49)
{
return (Integer + 1);
}
else
{
return Integer;
}
}
int main()
{
double a = 0.1;
double sigma = 0.01;
int delta_t = 1;
double M = -a * delta_t;
double V = sigma * sigma * delta_t;
double delta_r = sqrt(3 * V);
int count;
double PuValue;
double PmValue;
double PdValue;
int j_max;
int j_min;
j_max = Rounding(-0.184 / M);
j_min = -j_max;
std::vector<std::vector<double>> Pu((20), std::vector<double>(20));
std::vector<std::vector<double>> Pm((20), std::vector<double>(20));
std::vector<std::vector<double>> Pd((20), std::vector<double>(20));
std::cout << std::setprecision(10);
for (int i = 0; i <= 2; i++)
{
count = 0;
for (int j = i; j >= -i; j--)
{
count = count + 1;
if (j = j_max) // Exhibit 1C
{
PuValue = 7.0/6.0 + (j * j * M * M + 3 * j * M)/2.0;
PmValue = -1.0/3.0 - j * j * M * M - 2 * j * M;
PdValue = 1.0/6.0 + (j * j * M * M + j * M)/2.0;
}
else if (j = j_min) // Exhibit 1B
{
PuValue = 1.0/6.0 + (j * j * M * M - j * M)/2.0;
PmValue = -1.0/3.0 - j * j * M * M + 2 * j * M;
PdValue = 7.0/6.0 + (j * j * M * M - 3 * j * M)/2.0;
}
else
{
PuValue = 1.0/6.0 + (j * j * M * M + j * M)/2.0;
PmValue = 2.0/3.0 - j * j * M * M;
PdValue = 1.0/6.0 + (j * j * M * M - j * M)/2.0;
}
Pu[count][i] = PuValue;
Pm[count][i] = PmValue;
Pd[count][i] = PdValue;
std::cout << Pu[count][i] << ", ";
}
std::cout << std::endl;
}
return 0;
}
You are assigning instead of checking for equal: j_max to j in your if statements.
if (j = j_max)
// ^
else if (j = j_min)
// ^
Change if (j = j_max) to if (j == j_max),
And else if (j = j_min) to else if (j == j_min).
Correct the following if conditional check and all other instances of an if check
if(j=j_max)
with
if (j == j_max)
you are checking for an equality not assigning.
Your code was going into an infinite loop.
I'm implementing an algorithm, I excuse myself for the extreme for looping, haven't found a better way yet.
The problem is that at the second iteration at line 81 it gives a First-chance exception at 0x000000007707320E (ntdll.dll) in Test.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
void co_hog(Mat image, int offset, int blockSize, int nrBins, int cat) {
Mat img_x;
Mat img_y;
IplImage img = image;
Mat kern_x = (Mat_<char>(1, 3) << -1, 0, 1);
Mat kern_y = (Mat_<char>(3, 1) << -1, 0, 1);
filter2D(image, img_x, image.depth(), kern_x);
filter2D(image, img_y, image.depth(), kern_y);
Size imageSize = image.size();
int nrBlocksY = imageSize.height / blockSize;
int nrBlocksX = imageSize.width / blockSize;
int degreePerBin = 180 / nrBins;
Mat gradients = Mat(image.size(), CV_32FC1);
Mat magnitudes = Mat(image.size(), CV_32FC1);
for(int y = 0; y < image.rows; y++) {
for(int x = 0; x < image.cols; x++) {
float grad_x = (float)img_x.at<uchar>(y, x);
float grad_y = (float)img_y.at<uchar>(y, x);
gradients.at<float>(y, x) = abs(atan2(grad_y, grad_x) * 180 / PI);
magnitudes.at<float>(y, x) = sqrt(pow(grad_x, 2) + pow(grad_y, 2));
}
}
int bin_1, bin_2, bin_3, bin_4;
double theta_1, theta_2, theta_3, theta_4;
Mat H;
stringstream line(stringstream::in | stringstream::out);
line << cat << " ";
int index = 1;
for(int i = 0; i < nrBlocksY; i++) {
for(int j = 0; j < nrBlocksX; j++) {
Mat coOccMat = Mat::zeros(nrBins, nrBins, CV_32FC1);
for(int q = i * blockSize; q < (i * blockSize) + blockSize; q++) {
for(int p = j * blockSize; p < (j * blockSize) + blockSize; p++) {
for(int offy = -offset; offy < offset; offy++) {
for(int offx = -offset; offx < offset; offx++) {
if((q + offy) >= imageSize.height || (p + offx) >= imageSize.width || (q + offy) < 0 || (p + offx) < 0) {
continue;
}
float m_1 = magnitudes.at<float>(q, p);
float m_2 = magnitudes.at<float>(q + offy, p + offx);
float alpha = gradients.at<float>(q, p);
float beta = gradients.at<float>(q + offy, p + offx);
if(fmod(alpha / degreePerBin, 1) > 0.5) {
bin_1 = floor(alpha / degreePerBin);
bin_2 = bin_1 + 1;
} else {
bin_2 = floor(alpha / degreePerBin);
bin_1 = bin_2 - 1;
}
if(fmod(beta / degreePerBin, 1) > 0.5) {
bin_3 = floor(beta / degreePerBin);
bin_4 = bin_3 + 1;
} else {
bin_4 = floor(beta / degreePerBin);
bin_3 = bin_4 - 1;
}
theta_1 = (bin_1 * degreePerBin) + (degreePerBin / 2);
theta_2 = (bin_2 * degreePerBin) + (degreePerBin / 2);
theta_3 = (bin_3 * degreePerBin) + (degreePerBin / 2);
theta_4 = (bin_4 * degreePerBin) + (degreePerBin / 2);
coOccMat.at<float>(bin_1, bin_3) += (m_1 * (1 - (alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * (1 - (beta - theta_3) / (theta_4 - theta_1)));
coOccMat.at<float>(bin_1, bin_4) += (m_1 * (1 - (alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * ((beta - theta_3) / (theta_4 - theta_1)));
coOccMat.at<float>(bin_2, bin_3) += (m_1 * ((alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * (1 - (beta - theta_3) / (theta_4 - theta_1)));
coOccMat.at<float>(bin_2, bin_4) += (m_1 * ((alpha - theta_1) / (theta_2 - theta_1))) + (m_2 * ((beta - theta_3) / (theta_4 - theta_1)));
}
}
}
}
cout << coOccMat << endl;
-> Next statement to be called *passes the first time* H = coOccMat.reshape(0, 1);
normalize(H, H);
cout << H.size() << endl;
for(int i = 0; i < H.cols; ++i) {
for(int j = 0; j < H.rows; ++j) {
if(H.at<float>(j, i) > 0) {
line << index << ":" << H.at<float>(j, i) << " ";
}
index++;
}
}
cout << "Done" << index << endl;
}
}
}
Problem has been fixed, sometimes the value for a bin was set on -1 so it couldn't access it, debugging tools of visual studio couldn't point out where it went wrong.