I have a problem with calling this function:
void powell(float p[], float **xi, int n,
float ftol, int *iter, float *fret,
float (*func)(float []))
I don't know which argument must be under **xi to run my code.
Whole function below:
void powell(float p[], float** xi, int n, float ftol, int* iter, float* fret, float (*func)(float[]))
{
void linmin(float p[], float xi[], int n, float* fret, float (*func)(float[]));
int i, ibig, j;
float del, fp, fptt, t, *pt, *ptt, *xit;
pt = vector(1, n);
ptt = vector(1, n);
xit = vector(1, n);
*fret = (*func)(p);
for (j = 1; j <= n; j++)
pt[j] = p[j];
for (*iter = 1;; ++(*iter)) {
fp = (*fret);
ibig = 0;
del = 0.0;
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++)
xit[j] = xi[j][i];
fptt = (*fret);
linmin(p, xit, n, fret, func);
if (fptt - (*fret) > del) {
del = fptt - (*fret);
ibig = i;
}
}
if (2.0 * (fp - (*fret)) <= ftol * (fabs(fp) + fabs(*fret)) + TINY) {
free_vector(xit, 1, n);
free_vector(ptt, 1, n);
free_vector(pt, 1, n);
return;
}
if (*iter == ITMAX)
nrerror("powell exceeding maximum iterations.");
for (j = 1; j <= n; j++) {
ptt[j] = 2.0 * p[j] - pt[j];
xit[j] = p[j] - pt[j];
pt[j] = p[j];
}
fptt = (*func)(ptt);
if (fptt < fp) {
t = 2.0 * (fp - 2.0 * (*fret) + fptt) * SQR(fp - (*fret) - del) - del * SQR(fp - fptt);
if (t < 0.0) {
linmin(p, xit, n, fret, func);
for (j = 1; j <= n; j++) {
xi[j][ibig] = xi[j][n];
xi[j][n] = xit[j];
}
}
}
}
}
Thanks in advance.
A double pointer means that the function wants the address of a pointer.
void my_function(int **p_pointer)
{
*p_pointer = new int[42];
}
int main(void)
{
int * pointer = nullptr;
my_function(&pointer);
return 0;
}
In C++, the double pointer can be avoided by using reference:
void another_function(int *& pointer)
{
pointer = new int [256];
}
int main(void)
{
int p = nullptr;
another_function(p);
return 0;
}
One of the primary concerns with pointers is that they can point to anywhere, a defined location or not. Testing a pointer for validity is complex because it depends on the range (or ranges) that are valid for the current platform. With references, the reference is valid, by definition, so no validity checks need to be performed.
Related
well, i'm trying to run mexall.m in matlab and i get an Error using mex
\CLASS_facepipe_VJ_29-Sep-08b\utils\mre_disttransform.cxx: In function 'void
mexFunction(int, mxArray**, int, const mxArray**)':
\CLASS_facepipe_VJ_29-Sep-08b\utils\mre_disttransform.cxx:109:26: error: '_finite'
was not declared in this scope
here's the file (mre_disttransform.cxx)
#include "mex.h"
#include <float.h>
#ifdef _WIN32
#define isfinite _finite
#else
#include <cmath>
#include <math.h>
#endif
template<class T>
T MAX(T x, T y)
{
return (x > y) ? x : y;
}
const double big = 1e200;
// [D,L] = mre_disttransform(I)
void DT1D(const double *f, int n, int *v, double *z, double *d, int *l)
{
int k = 0;
v[0] = 0;
z[0] = -big;
z[1] = big;
for (int q = 1; q <= n - 1; q++)
{
double s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
while (s <= z[k])
{
k--;
s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]);
}
k++;
v[k] = q;
z[k] = s;
z[k + 1] = big;
}
k = 0;
for (int q = 0; q <= n - 1; q++)
{
while (z[k + 1] < q)
k++;
*(d++) = (q - v[k]) * (q - v[k]) + f[v[k]];
*(l++) = v[k];
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nrhs != 1)
mexErrMsgTxt("1 input arguments expected.");
if (nlhs != 2)
mexErrMsgTxt("2 distput arguments expected.");
if (!(mxIsDouble(prhs[0]) || mxIsLogical(prhs[0])) || mxIsComplex(prhs[0]) ||
mxGetNumberOfDimensions(prhs[0]) != 2)
mexErrMsgTxt("input 1 must be a double matrix");
int ih = mxGetM(prhs[0]), iw = mxGetN(prhs[0]);
plhs[0] = mxCreateDoubleMatrix(ih, iw, mxREAL);
double *dist = mxGetPr(plhs[0]);
plhs[1] = mxCreateNumericMatrix(ih, iw, mxINT32_CLASS, mxREAL);
int *inds = (int *) mxGetData(plhs[1]);
double *f = (double *) mxMalloc(MAX(iw, ih) * sizeof(double));
double *d = (double *) mxMalloc(MAX(iw, ih) * sizeof(double));
double *z = (double *) mxMalloc((MAX(iw, ih) + 1) * sizeof(double));
int *v = (int *) mxMalloc(MAX(iw, ih) * sizeof(int));
int *l = (int *) mxMalloc(MAX(iw, ih) * sizeof(int));
double *distp;
int *indp;
if (mxIsLogical(prhs[0]))
{
const mxLogical *imgp = mxGetLogicals(prhs[0]);
distp = dist;
indp = inds;
for (int x = 0, l0 = 1; x < iw; x++, l0 += ih)
{
for (int y = 0; y < ih; y++)
f[y] = *(imgp++) ? 0 : big;
DT1D(f, ih, v, z, d, l);
for (int y = 0; y < ih; y++)
{
*(distp++) = d[y];
*(indp++) = l[y] + l0;
}
}
}
else
{
const double *imgp = mxGetPr(prhs[0]);
distp = dist;
indp = inds;
for (int x = 0, l0 = 1; x < iw; x++, l0 += ih)
{
for (int y = 0; y < ih; y++, imgp++)
f[y] = isfinite(*imgp) ? *imgp : (*imgp > 0 ? big : -big);
DT1D(f, ih, v, z, d, l);
for (int y = 0; y < ih; y++)
{
*(distp++) = d[y];
*(indp++) = l[y] + l0;
}
}
}
distp = dist;
indp = inds;
for (int y = 0; y < ih; y++, distp++, indp++)
{
const double *srcp = distp;
for (int x = 0; x < iw; x++, srcp += ih)
f[x] = *srcp;
DT1D(f, iw, v, z, d, l);
for (int x = 0; x < iw; x++)
l[x] = indp[l[x] * ih];
double *dp = distp;
int *lp = indp;
for (int x = 0; x < iw; x++, dp += ih, lp += ih)
{
*dp = d[x];
*lp = l[x];
}
}
mxFree(l);
mxFree(v);
mxFree(z);
mxFree(d);
mxFree(f);
}
i'm completely new to this and i just want to install the package so the matlab would work
thanks in advance :)
void TableInsert(SLinkListType &L, RedType d[], int n)
/* 由数组D建立n个元素的表插入排序的静态链表L */
{
int i, p, q;
L.r[0].rc.key = INT_MAX;
L.r[0].next = 0;
for (i = 0; i < n; i++)
{
L.r[i + 1].rc = d[i];
q = 0;
p = L.r[0].next;
while (L.r[p].rc.key <= L.r[i + 1].rc.key)
{
q = p;
p = L.r[p].next;
}
L.r[i + 1].next = p;
L.r[q].next = i + 1;
}
L.length = n;
}//TableInsert
void Arrange(SLinkListType &L)
{
int i, p, q;
SLNode t;
p = L.r[0].next;
for (i = 1; i < L.length; i++)
{
while (p < i)
p = L.r[p].next;
q = L.r[p].next;
if (p != i)
{
t = L.r[p]; /* 交换记录,使第i个记录到位 */
L.r[p] = L.r[i];
L.r[i] = t;
L.r[i].next = p;
}
p = q; /* p指示尚未调整的表尾,为找第i+1个记录作准备 */
}
}//Arrange
void Sort(SLinkListType L, int adr[])
/* 求得adr[1..L.length],adr[i]为静态链表L的第i个最小记录的序号 */
{
int i = 1, p = L.r[0].next;
while (p)
{
adr[i++];
p = L.r[p].next;
}
}//Sort
void ReArrange(SLinkListType &L, int adr[])
/* adr给出静态链表L的有序次序,即L.r[adr[i]]是第i小的记录。 */
{
int i, j, k = 0;
for (i = 1; i < L.length; i++)
{
if (adr[i] != i)
{
j = i;
L.r[0] = L.r[i];
while (adr[j] != i)
/* 调整(*L).r[adr[j]]的记录到位直到adr[j]=i为止 */
{
k = adr[j];
printf("%d", k);
/* 如:adr[1] = 6,则 K = 6,将 r[6] 赋值到 r[1], 同时同步adr[], 然后将 adr[1] 移动 adr[6]*/
L.r[j] = L.r[k]; /* L.r[j] = L.r[adr[j]] */
adr[j] = j;
j = k; /* 记录按序到位 */
}
L.r[j] = L.r[0]; /* L.r[6] = L.r[0] */
adr[j] = j; /* 同步 adr[] */
}
}
}//ReArrange
void Print(SLinkListType L)
{
int i;
for (i = 1; i <= L.length; i++)
{
printf("key=%d ord=%d next=%d\n", L.r[i].rc.key, L.r[i].rc.otherinfo, L.r[i].next);
}
}//Print
#define N 8
void main()
{
RedType d[N] = { {49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8} };
SLinkListType a, b;
int *adr = NULL, i = 0; /* 内存分配有误,adr 的值超出范围 */
TableInsert(a, d, N);
b = a; /* 复制静态链表l2与l1相同 */
printf("排序前:\n");
Print(a);
Arrange(a);
printf("a排序后:\n");
Print(a);
adr = (int *)malloc((b.length + 1) * sizeof(int));
Sort(b, adr);
for (i = 1; i <= b.length; ++i)
{
printf("adr[%d] = %d", i, adr[i]);
}
printf("\n");
ReArrange(b, adr);
printf("b排序后:\n");
Print(b);
}
why when i defined int *adr = NULL i already let it equal NULL, but the value of adr out of the limit, and get an error: the Read rights conflict, how to define a pointer variable, so that the system don`t distribution a unknown pointer value. if define a NULL pointer, what is the pointer value , is my initialization was wrong? how to initialization a pointer
If I understand you correctly, you're stepping through the code in a debugger, and stopped at the line
int *adr = NULL, i = 0;
and wonder why adr is not a null pointer?
Then that's because the initialization haven't happened yet. If you take one more step then the initialization will happen and adr should become NULL.
Instead of " int *adr = NULL; , try to use
int *adr
adr = new int;
If you use int *adr = NULL , it will cause to create an insufficient memory .
adr = new int; - creates new dynamic memory. NULL is used to after deleting pointer !!!
I have two overloaded functions: "ChooseElements", which chooses elements from passed array, and "SortElements", which sorts elements of passed array. One pair works with INT data, and another one with FLOAT.
int * ChooseElements(int * X, int n, int & m)
{
int * Y = NULL;
for (int i = 0; i < n; i++)
{
if (X[i] > 0)
{
if (Y == NULL)
{
m = 1;
Y = new int[1];
Y[0] = X[i];
}
else
{
m++;
Y = (int *)realloc(Y, sizeof(int) * m);
Y[m - 1] = X[i];
}
}
}
return Y;
}
float * ChooseElements(float * X, int n, int & m)
{
float * Y = NULL;
for (int i = 0; i < n; i++)
{
if (X[i] > 0)
{
if (Y == NULL)
{
m = 1;
Y = new float[1];
Y[0] = X[i];
}
else
{
m++;
Y = (float *)realloc(Y, sizeof(float) * m);
Y[m - 1] = X[i];
}
}
}
return Y;
}
and
int * SortElements(int m, int *& Y)
{
for (int i = 1; i < m; i++)
{
for (int j = 0; j < m - i; j++)
{
if (Y[j] > Y[j + 1])
{
int Temp = Y[j];
Y[j] = Y[j + 1];
Y[j + 1] = Temp;
}
}
}
return Y;
}
float * SortElements(int m, float *& Y)
{
for (int i = 1; i < m; i++)
{
for (int j = 0; j < m - i; j++)
{
if (Y[j] > Y[j + 1])
{
float Temp = Y[j];
Y[j] = Y[j + 1];
Y[j + 1] = Temp;
}
}
}
return Y;
}
What I want to do is pass first function as argument to second one. Like that:
int n, m;
int * X = NULL, * Y = NULL;
/* ...
Some code in which n and X are initialized
... */
Y = SortElements(m, ChooseElements(X, n, m));
However, when I try to do that, Visual Studio 2017 tells me:
no instance of overloaded function "SortElements" matches the argument list
argument types are: (int, int *)
If I do this instead:
Y = ChooseElements(X, n, m);
Y = SortElements(m, Y);
everything works fine.
If I remove overloads and leave only INT pair and once again try
int n, m;
int * X = NULL, * Y = NULL;
/* ...
Some code in which n and X are initialized
... */
Y = SortElements(m, ChooseElements(X, n, m));
I get another problem:
int *ChooseElements(int *X, int n, int &m)
initial value of reference to non-const value must be an lvalue
What am I doing wrong? My teacher asks for a function which uses another function as an argument. What I have written does not work, and I have no idea what could be done here.
In your int * SortElements(int m, int *& Y)
function you are using : int *& Y. So you have a reference to a int pointer. My guess is that you don't need that.
You can just use int * Y as a parameter as a solution.
Int *& Y - needs an lvalue(like your variable Y) but your ChooseElements function returns only a temporary object(rvalue) because you are returning by value.
this is a part of my original code, the code is too big to put it all in here,
anyway my question is only related to Sads 4D matrix,
I don't want to use the int**** like it was suggested to me in my previous question
int main()
{
//4D matrix
int**** Sads = new int***[inputImage->HeightLines];
for (size_t i = 0; i < inputImage->HeightLines; i++)
{
Sads[i] = new int**[inputImage->WidthColumns];
for (size_t j = 0; j < inputImage->WidthColumns; j++)
{
Sads[i][j] = new int*[W_SIZE];
for (size_t k = 0; k < W_SIZE; k++)
{
Sads[i][j][k] = new int[W_SIZE];
}
}
}
ProcessRowsLoop(20, 1904, Sads);
}
void ProcessRowsLoop(int m_support, int m_height, int**** sads)
{
for (int row_in = m_support - 1; row_in < m_Height_in; row_in += BNLM_OUT_SZ)
{
ProcessRow( &Sads[indexRow]);
}
}
void ProcessRow(int**** sads)
{
int m_SAD_00[W_SIZE][W_SIZE];
int m_SAD_01[W_SIZE][W_SIZE];
int m_SAD_10[W_SIZE][W_SIZE];
int m_SAD_11[W_SIZE][W_SIZE];
RunAlgo(m_support, m_SAD_00, m_SAD_01, m_SAD_10, m_SAD_11, m_CP_00, m_CP_01, m_CP_10, m_CP_11, m_ColumnSADUp, m_ColumnSADDown);
for (size_t i = 0; i < W_SIZE; i++)
{
for (size_t j = 0; j < W_SIZE; j++)
{
Sads[0][m_col_out][i][j] = (m_SAD_00[i][j] + color_penalty_weight * m_CP_00[i][j]) / (sqrt(m_sigma_patch[0][0] / pow(mnm, 2)));
Sads[0][m_col_out + 1][i][j] = (m_SAD_01[i][j] + color_penalty_weight * m_CP_01[i][j]) / (sqrt(m_sigma_patch[0][1] / pow(mnm, 2)));
Sads[1][m_col_out][i][j] = (m_SAD_10[i][j] + color_penalty_weight + m_CP_10[i][j]) / (sqrt(m_sigma_patch[1][0] / pow(mnm, 2)));
Sads[1][m_col_out + 1][i][j] = (m_SAD_11[i][j] + color_penalty_weight + m_CP_11[i][j]) / (sqrt(m_sigma_patch[1][1] / pow(mnm, 2)));
}
}
}
In my new code I would like to replace the 4D matrix int**** Sads, with
struct VectorFourD
{
private:
int _width, _height;
int _w_size;
std::vector<int> _vec;
public:
VectorFourD(int width, int height, int size) : _width(width), _height(height), _w_size(size), _vec(totalSize())
{
}
auto totalSize() const-> int
{
return _width * _height * _w_size * _w_size;
}
int* at(int a)
{
return _vec.data() + (a * _height * _w_size * _w_size);
}
int* at(int a, int b)
{
return at(a) + (b * _w_size * _w_size);
}
int *at(int a, int b, int c)
{
return at(a, b) + (c* _w_size);
}
int& at(int a, int b, int c, int d)
{
return *(at(a, b, c) + d);
}
};
you can see that i'm iterating two lines at the same time in the function processrow()
running over
Sads[0][m_col_out][i][j], Sads[0][m_col_out + 1][i][j],
Sads[1][m_col_out][i][j], Sads[1][m_col_out + 1][i][j]
at the same time, my question is how do I change my code to work with the new 4dvector for example
int main()
{
VectorFourD SadsVec = VectorFourD(inputImage->HeightLines, inputImage->WidthColumns, W_SIZE);
ProcessRowsLoop(20, 1904, SadsVec);
}
also change the function void ProcessRowsLoop(int m_support, int m_height, VectorFourD* SadsVec)
but i don't know how to continue from here, can you please help?
I implemented the Jacobi algorithm using TBB and it works just fine. Then I parallelized the convergence calculation using a reduction, but for some reason if I use more than 1 logical core I get an segmentation fault and i can't figure out why.
I can use more than 1 thread on a system that has only 1 logical core.
The same implementation using OpenMP works without a hassle
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <tbb/parallel_for.h>
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>
#include <tbb/task_scheduler_init.h>
#include <tbb/tick_count.h>
// ----------------------------------------------------------------
#define SIZE 1024
#define RESIDUO 0.0009f*SIZE
#define THREADS 2
using namespace tbb;
// ----------------------------------------------------------------
struct Sum {
float ret;
float (*a)[SIZE];
float (*x);
float (*b);
Sum(float A[SIZE][SIZE], float X[SIZE], float B[SIZE]) : ret(0), a(A), x(X), b(B) {}
Sum( Sum&, split ) {ret = 0;}
void operator()( const blocked_range<int>& r ) {
float temp = ret;
for( int i = r.begin(); i != r.end(); i++ ) {
float sum = 0.0f;
for(int j = 0; j < SIZE; j++){
sum += a[i][j] * x[j];
}
temp += pow(b[i] - sum, 2);
}
ret = temp;
}
void join( Sum& rhs ) {ret += rhs.ret;}
};
/*
// || b - Ax ||
*/
int converge(float a[SIZE][SIZE], float x[SIZE], float b[SIZE]){
Sum total(a, x, b);
parallel_reduce( blocked_range<int>(0, SIZE), total );
float norm = sqrt(total.ret);
printf("Ret: %f | Residuo: %f\n", total.ret, norm);
return (norm <= RESIDUO);
}
// ----------------------------------------------------------------
float randomFloat()
{
float r = (float)rand()/(float)RAND_MAX;
return r;
}
// ----------------------------------------------------------------
int check_ddm(float (*a)[SIZE]){
float sum = 0.0f;
int i = 0, j = 0;
for(i = 0; i < SIZE; i++){
sum = 0.0f;
for(j = 0; j < SIZE; j++){
if(i != j){
sum += a[i][j];
}
}
if(a[i][i] < sum){
printf("line: %d, sum: %f, a[i][i]: %f \n", i, sum, a[i][i]);
for(j = 0; j < SIZE; j++){
if(i != j) printf("%f ", a[i][j]);
else printf("(%f) ", a[i][j]);
}
printf("\n");
return 0;
}
}
return 1;
}
// ----------------------------------------------------------------
int generate_ddm(float (*a)[SIZE], float *b)
{
int i = 0, j = 0;
float line = 0.0f;
for(i = 0; i < SIZE; i++){
line = 0.0f;
for(j = 0; j < SIZE; j++){
if(i != j){
a[i][j] = randomFloat();
}
line += a[i][j];
}
a[i][i] = SIZE;
b[i] = line + SIZE;
}
return check_ddm(a);
}
// ----------------------------------------------------------------
int main( )
{
float (*x)[SIZE] = (float(*)[SIZE])malloc(sizeof *x * 2);
float (*a)[SIZE] = (float(*)[SIZE])malloc(sizeof *a * SIZE);
float (*b) = (float*)malloc(sizeof(float) * SIZE);
int i = 0, j = 0;
float delta = 0.0f;
int read = 0;
int write = 1;
srand(time(NULL));
tbb::task_scheduler_init init(THREADS);
// set up initial solution
for(i = 0; i < SIZE; i++){
x[0][i] = i;
x[1][i] = i;
}
// generate a diagonal dominant matrix
if(!generate_ddm(a, b)){
printf("Array generated is not ddm!\n");
return 1;
}
tick_count startTime = tick_count::now();
while(!converge(a, x[write], b)){
read = !read;
write = !write;
parallel_for(blocked_range<int>(0,SIZE),
[&] (const blocked_range<int>& r) {
for (int i = r.begin(); i < r.end(); i++) {
float delta = 0.0f;
for(int j = 0; j < SIZE; j++){
if(j != i){
delta += a[i][j] * x[read][j];
}
}
x[write][i] = (b[i] - delta) / a[i][i];
}
});
}
tick_count lastTime = tick_count::now();
float walltime = (lastTime - startTime).seconds();
printf("tbb %f\n", walltime);
converge(a, x[write], b);
printf("x0: %f | x%d: %f\n", x[write][0], SIZE-1, x[write][SIZE-1]);
free(a);
free(b);
free(x);
return 0;
}
The segfault occurs on the following line inside the Sum class:
sum += a[i][j] * x[j];
And if I change that line to
float tmpa = a[i][j];
float tmpx = x[j];
sum += tmpa * tmpx;
The error continues to be on
sum += tmpa * tmpx;
In the original version, the "splitting constructor" left a, x, and b undefined. They need to be copied from the incoming Sum& argument. E.g., change the splitting constructor to:
Sum( Sum& s, split ) {a=s.a; b=s.b; x=s.x; ret = 0;}
Changing the Class to a lambda expression solved the problem. It maybe a bug in TBB's parallel_reduce
int converge(float a[SIZE][SIZE], float x[SIZE], float b[SIZE]){
float val = 0.0f;
val = parallel_reduce(
blocked_range<int>(0, SIZE),
0.0f,
[&]( const blocked_range<int>& r, float init )->float {
float temp = init;
for(int i = r.begin(); i != r.end(); i++ ) {
float sum = 0.0f;
for(int j = 0; j < SIZE; j++){
sum += a[i][j] * x[j];
}
temp += pow(b[i] - sum, 2);
}
return temp;
},
[]( float x, float y)->float{
return x+y;
}
);
float norm = sqrt(val);
printf("Ret: %f | Residuo: %f\n", val, norm);
return (norm <= RESIDUO);
}