C++ Returning double** from matrix - c++

Hi everyone I got a trouble with the returning element of a function. I need to return a double pointer to pointer "double**". But I got a double[][] matrix.
Here is the code:
double** createPalette(int r, int g, int b) {
double incR = 1 / r, incG = 1 / g, incB = 1 / b;
double Cp[r * g * b][3];
for (int i = 0; i < r; i++) {
for (int j = 0; j < g; j++) {
for (int k = 0; k < b; k++) {
Cp[i * r + j * g + k][0] = incR * i;
Cp[i * r + j * g + k][1] = incG * j;
Cp[i * r + j * g + k][2] = incB * k;
}
}
}
return Cp; //return &cp... (?)
}
I was looking for on internet, but I only found about simple pointer, no pointer to pointers.What should I do?
Thanks for all.

I think you know the value of r,g,b,so you can get the size of the matrix,you can do like this
void createPalette(int r, int g, int b, double matrix[][3])

Related

object with type qualifiers are not compatible with the member function

I was making a ray tracer and in the header it gave me this error c++ in the header file. It has to do with the perlin_interp return. Help me please! thanks
the two errors:
Error C2662 'double perlin::perlin_interp(vec3 [][2][2],double,double,double)': cannot convert 'this' pointer from 'const perlin' to 'perlin &' RayTracer c:\users\graha\source\repos\raytracer\perlin.h 57
Severity Code Description Project File Line Suppression State
Error (active) E1086 the object has type qualifiers that are not compatible with the member function "perlin::perlin_interp" RayTracer C:\Users\graha\source\repos\RayTracer\perlin.h 57
#include "vec3.h"
#include "rtweekend.h"
#include <random>
inline double trilinear_interp(double c[2][2][2], double u, double v, double w) {
auto accum = 0.0;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
accum += (i*u + (1 - i)*(1 - u))*
(j*v + (1 - j)*(1 - v))*
(k*w + (1 - k)*(1 - w))*c[i][j][k];
return accum;
}
class perlin {
public:
perlin() {
ranvec = new vec3[point_count];
for (int i = 0; i < point_count; ++i) {
ranvec[i] = unit_vector(vec3::random(-1, 1));
}
perm_x = perlin_generate_perm();
perm_y = perlin_generate_perm();
perm_z = perlin_generate_perm();
}
~perlin() {
delete[] ranvec;
delete[] perm_x;
delete[] perm_y;
delete[] perm_z;
}
double noise(const point3 p) const{
auto u = p.x() - floor(p.x());
auto v = p.y() - floor(p.y());
auto w = p.z() - floor(p.z());
int i = floor(p.x());
int j = floor(p.y());
int k = floor(p.z());
vec3 c[2][2][2];
for (int di = 0; di < 2; di++)
for (int dj = 0; dj < 2; dj++)
for (int dk = 0; dk < 2; dk++)
c[di][dj][dk] = ranvec[
perm_x[(i + di) & 255] ^
perm_y[(j + dj) & 255] ^
perm_z[(k + dk) & 255]
];
return perlin_interp(c, u, v, w); //problem area
}
private:
vec3* ranvec;
static const int point_count = 256;
double* ranfloat;
int* perm_x;
int* perm_y;
int* perm_z;
static int* perlin_generate_perm() {
auto p = new int[point_count];
for (int i = 0; i < perlin::point_count; i++)
p[i] = i;
permute(p, point_count);
return p;
}
static void permute(int* p, int n) {
for (int i = n - 1; i > 0; i--) {
int target = random_int(0, i);
int tmp = p[i];
p[i] = p[target];
p[target] = tmp;
}
}
inline double perlin_interp(vec3 c[2][2][2], double u, double v, double w) {
auto uu = u * u*(3 - 2 * u);
auto vv = v * v*(3 - 2 * v);
auto ww = w * w*(3 - 2 * w);
auto accum = 0.0;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++) {
vec3 weight_v(u - i, v - j, w - k);
accum += (i*uu + (1 - i)*(1 - uu))
* (j*vv + (1 - j)*(1 - vv))
* (k*ww + (1 - k)*(1 - ww))
* dot(c[i][j][k], weight_v);
}
return accum;
}
};

Implementing modular Runge-kutta 4th order method for a n-dimension system

i'm trying to make my runge-kutta 4th order code modular. I don't want to have to write and declare the code everytime I use it, but declare it in a .hpp and a .cpp file to use it separetely. But i'm having some problems. Generally I want to solve a n-dimension system of equations. For that I use two functions: one for the system of equations and another for the runge-kutta method as follows:
double F(double t, double x[], int eq)
{
// System equations
if (eq == 0) { return (x[1]); }
else if (eq == 1) { return (gama * sin(OMEGA*t) - zeta * x[1] - alpha * x[0] - beta * pow(x[0], 3) - chi * x[2]); }
else if (eq == 2) { return (-kappa * x[1] - phi * x[2]); }
else { return 0; }
}
void rk4(double &t, double x[], double step)
{
double x_temp1[sistvar], x_temp2[sistvar], x_temp3[sistvar];
double k1[sistvar], k2[sistvar], k3[sistvar], k4[sistvar];
int j;
for (j = 0; j < sistvar; j++)
{
x_temp1[j] = x[j] + 0.5*(k1[j] = step * F(t, x, j));
}
for (j = 0; j < sistvar; j++)
{
x_temp2[j] = x[j] + 0.5*(k2[j] = step * F(t + 0.5 * step, x_temp1, j));
}
for (j = 0; j < sistvar; j++)
{
x_temp3[j] = x[j] + (k3[j] = step * F(t + 0.5 * step, x_temp2, j));
}
for (j = 0; j < sistvar; j++)
{
k4[j] = step * F(t + step, x_temp3, j);
}
for (j = 0; j < sistvar; j++)
{
x[j] += (k1[j] + 2 * k2[j] + 2 * k3[j] + k4[j]) / 6.0;
}
t += step;
}
The above code works and it is validated. However it has some dependencies as it uses some global variables to work:
gama, OMEGA, zeta, alpha, beta, chi, kappa and phi are global variables that I want to read from a .txt file. I already manage to do that, however only in a single .cpp file with all code included.
Also, sistvar is the system dimension and also a global variable. I'm trying to enter it as an argument in F. But the way it is written seems to give errors as sistvar is a const and can't be changed as a variable and I can't put variables inside an array's size.
In addition, the two functions has an interdependency as when a call F inside rk4, eq number is needeed.
Could you give me tips in how to do that? I already searched and read books about this and could not find an answer for it. It is probably an easy task but i'm relatively new in c/c++ programming languages.
Thanks in advance!
* EDITED (Tried to implement using std::vector)*
double F(double t, std::vector<double> x, int eq)
{
// System Equations
if (eq == 0) { return (x[1]); }
else if (eq == 1) { return (gama * sin(OMEGA*t) - zeta * x[1] - alpha * x[0] - beta * pow(x[0], 3) - chi * x[2]); }
else if (eq == 2) { return (-kappa * x[1] - phi * x[2]); }
else { return 0; }
}
double rk4(double &t, std::vector<double> &x, double step, const int dim)
{
std::vector<double> x_temp1(dim), x_temp2(dim), x_temp3(dim);
std::vector<double> k1(dim), k2(dim), k3(dim), k4(dim);
int j;
for (j = 0; j < dim; j++) {
x_temp1[j] = x[j] + 0.5*(k1[j] = step * F(t, x, j));
}
for (j = 0; j < dim; j++) {
x_temp2[j] = x[j] + 0.5*(k2[j] = step * F(t + 0.5 * step, x_temp1, j));
}
for (j = 0; j < dim; j++) {
x_temp3[j] = x[j] + (k3[j] = step * F(t + 0.5 * step, x_temp2, j));
}
for (j = 0; j < dim; j++) {
k4[j] = step * F(t + step, x_temp3, j);
}
for (j = 0; j < dim; j++) {
x[j] += (k1[j] + 2 * k2[j] + 2 * k3[j] + k4[j]) / 6.0;
}
t += step;
for (j = 0; j < dim; j++) {
return x[j];
}
}
vector array
2.434 s | | 0.859 s
2.443 s | | 0.845 s
2.314 s | | 0.883 s
2.418 s | | 0.884 s
2.505 s | | 0.852 s
2.428 s | | 0.923 s
2.097 s | | 0.814 s
2.266 s | | 0.922 s
2.133 s | | 0.954 s
2.266 s | | 0.868 s
_______ _______
average = 2.330 s average = 0.880 s
Using vector function where the vector arithmetic is taken from Eigen3
#include <eigen3/Eigen/Dense>
using namespace Eigen;
of the same parts as discussed in the question could look like (inspired by function pointer with Eigen)
VectorXd Func(const double t, const VectorXd& x)
{ // equations for solving simple harmonic oscillator
Vector3d dxdt;
dxdt[0] = x[1];
dxdt[1] = gama * sin(OMEGA*t) - zeta * x[1] - alpha * x[0] - beta * pow(x[0], 3) - chi * x[2];
dxdt[2] = -kappa * x[1] - phi * x[2];
return dxdt;
}
MatrixXd RK4(VectorXd Func(double t, const VectorXd& y), const Ref<const VectorXd>& y0, double t, double h, int step_num)
{
MatrixXd y(y0.rows(), step_num );
VectorXd k1, k2, k3, k4;
y.col(0) = y0;
for (int i=1; i<step_num; i++){
k1 = Func(t, y.col(i-1));
k2 = Func(t+0.5*h, y.col(i-1)+0.5*h*k1);
k3 = Func(t+0.5*h, y.col(i-1)+0.5*h*k2);
k4 = Func(t+h, y.col(i-1)+h*k3);
y.col(i) = y.col(i-1) + (k1 + 2*k2 + 2*k3 + k4)*h/6;
t = t+h;
}
return y.transpose();
}
Passing a vector to a function to be filled apparently requires some higher template contemplations in Eigen.

From mathematic function to c++ code

I am trying to implement this F(S) function:
bellow is my code but is not working:
double EnergyFunction::evaluate(vector<short> field) {
double e = 0.0;
for (int k = 1; k < field.size() - 1; k++){
double c = 0.0;
for (int i = 1; i < field.size() - k; i++) {
c += field[i] * field[i + k];
}
e += pow(c, 2);
}
double f = pow(field.size(), 2) / ( 2 * e );
return f;
}
For example F(S) function should return value 8644 for vector:
1,1,1,-1,-1,-1,1,-1,1,1,-1,1,-1,1,-1,1,-1,-1,1,1,1,1,-1,-1,-1,1,1,1,1,-1,1,-1,1,1,-1,-1,1,1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1,1,1,-1,1,-1,-1,1,1,-1,1,-1,1,-1,1,-1,1,-1,1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,-1,1,1,-1,1,1,-1,1,-1,1,1,1,-1,-1,1,1,-1,-1,1,1,1,1,1,1,1,1,-1,1,-1,1,-1,1,-1,-1,1,-1,-1,1,-1,-1,1,-1,-1,-1,-1,-1,1,1,1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,1,1,1,1,1,-1,1,-1,1,-1,1,1,1,1,1,1,-1,1,-1,-1,-1,1,-1,1,1,-1,-1,-1,-1,1,-1,-1,-1,1,1,-1,-1,1,1,1,-1,-1,1,1,1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,-1,-1,1,-1,-1,-1,1,-1,-1,1,1,-1,-1,-1,-1,-1,1,-1,-1,-1,1,1,-1,1,1,-1,-1,-1,1,-1,-1,1,-1,-1,-1,1,1,1,-1,-1,-1,-1,1,1,1,-1,1,-1,-1,1,-1,1,1,-1,-1,-1,-1,1,-1,1,1,1,1,1,1,-1,1,1,1,-1,-1,-1,-1,1,-1,1,1,1,1,-1,1,1,1,1,1,-1,-1,-1,1,-1,-1,1,1,1,-1,1,1,1,-1,1,1
I need another par of eyes to look at my code because I am a bit lost here. :)
after refactoring:
double EnergyFunction::evaluate(vector<short> field) {
double e = 0.0;
int l = field.size()
for (int k = 1; k < l; k++){
double c = 0.0;
for (int i = 0, j = k; j < l; i++, j++) {
c += field[i] * field[j];
}
e += c*c;
}
return l*l / ( e+e );
}
explanation:
1. we need to iterate (L-1) times
2. we need to shift the base and offset indexes until we reach the last one
3. c*c and e+e are quicker and easier to read
You are mapping variables into different ranges using the same names, which is always going to be confusing. Better is to keep ranges and names the same as in the math, and only subtract one for 0-base indexes at indexing time. Also might as well use L explicitly:
int L = field.size();
for (int k = 1; k <= L-1; k++){
...
for (int i = 1; i <= L-k; i++) {
c += field[i -1] * field[i+k -1];
...

I need to specify the size of an array dynamically

I have a Nx3 array which I need to fill as a function (so vector isn't an option). I already know how big N as as I feed it into the function as a parameter. I still get this stupid error of "must have a constant value", my code is:
double bspline_plot(double CP[], double Knot[], const int N, int d, int ncontrol, double *A){
// CP are the control points
//Knot is the knot vector
//N is the number of internal point you want in each segment
//d is the degree of the polynomials
double min_x, max_x, dx;
double *x_1;
x_1 = new double[N];
double A[N][2];
int i, j, M, L;
min_x = min(Knot);
max_x = max(Knot);
dx = (max_x - min_x) / N;
for (i = 0; i <= N; i = i + 1)
{
x_1[i] = min_x + dx*i;
}
M = ncontrol;
L = (sizeof(Knot) / sizeof(*Knot));
if (L < d + M + 1) // This checks if the number of control points are positive
{
printf("Incorrectly defined knot vector\n");
return;
}
else //This is the Cox - deBoor algorithm
{
for (i = 0; i <= N; i = i + 1)
{
for (j = 0; j <= L - 1; j = j + 1)
{
A[i][1] = A[i][1] + CP[j, 1] * CdB(j, d, x_1[i], Knot);
A[i][2] = A[i][2] + CP[j, 2] * CdB(j, d, x_1[i], Knot);
A[i][3] = A[i][3] + CP[j, 3] * CdB(j, d, x_1[i], Knot);
}
A[N][1] = CP[L, 2];
A[N][2] = CP[L, 2];
A[N][3] = CP[L, 1];
}
}
return A;
}
My other option is to feed in an array and then find it's values in the function but that seems a bit silly.
try to use std::vector in following way:
std::vector<std::vector<double>> A( N );
for( auto& row : A )
row.resize( M );
or
std::vector<std::vector<double>> A( N, std::vector<double>( M ));
From a quick inspection, the problem in your C++ code appears to be the following array declaration:
double A[N][2];
You need to dynamically allocate this 2d array as follows:
double** A = new double*[N];
for (int i=0; i<N; ++i)
A[i] = new double[2];
Have a look at this SO article for more information.
In the end I had to split A up into three vectors and change the output of the function from double to void and read in the (now) three vectors as double*. I can then just change the contents of the vectors and it now is showing no errors.

Matrix multiplication using 1d arrays

I'm trying to multiply two matrices stored inside 1d arrays.
I'm using this function, but my program crashes, I assume due to an out of bounds error.
However, I have no (easy) ability to debug, so I have to decide if my code is correct, and to me it seems it is...
void SampleUtils::multiplyMatrices(float* matA, int rA, int cA, float* matB,
int rB, int cB, float* matC, int rC, int cC) {
for (int i = 0; i <= rA; i++) {
for (int j = 0; j <= cB; j++) {
float sum = 0.0;
for (int k = 0; k <= rB; k++)
sum = sum + matA[i * cA + k] * matB[k * cB + j];
matC[i * cC + j] = sum;
}
}
So, can anyone find out what I did wrong?
Thanks...
Chances are you mean < instead of <= in your for loops.
Try to use i < rA , j < cB, k < rB in your for