What happens when we calculate this-(object of current class) - c++

i have class name DPPoint what happens when we calculate this-(object of DPPoint) in same class and assign value to a variable of type int

If I understand correctly the question is about this:
DPPoint* p1 = new DPPoint;
DPPoint* p2 = new DPPoint;
int k = p1 - p2; // what is k?
That's perfectly valid code. It's called "pointer arithmetic". It will give you distance between p1 and p2 in sizes of DPPoint.
DPPoint array [10];
int k = &array[5] - &array[3]; // k = 2
int n = (int)&array[5] - (int)&array[3]; // n = 2 * sizeof (DPPoint)
(&array[5] == &array[3] + 2); // true
(&array[5] == array + 5); // also true
The pointers don't have to be in the same array. Can be two random addresses in memory (skipping alignment issues for simplicity).

Related

C++ operation overloading for multiple types with variadic template initializer list

Hello i´ve created a simple 2D coordinate class (Point2D) and i want to overload this class with some basic operations ( + - * / ) for some basic types(short,int,double....) so i thought i should use a template. The problem is that i get some strage numbers(i think that these are the max size of the type) as x and y value back so therefore it ignores my e.g addition.
Point2D *p = new Point2D(5, 7) //everything works fine here x=5 y=7
Point2D *p = new Point2D(5, 7) + 10;//x= 1.09 * e^-38 same for y but it want x=15 and y=17
Heres the definition of my operation overloading function :
template<class T>
Point2D Point2D::operator+(initializer_list<T> elementList)
{
for (auto elem : elementList)
{
this->x += elem;
this->y += elem;
}
return Point2D(x,y);
}
The behaviour of
Point2D *p = new Point2D(5, 7) + 10;
is undefined. The right hand side is grouped as (new Point2D(5, 7)) + 10 which is adding 10 lots of sizeof(Point2D) to the Point2D* pointer returned back from new!
You are not allowed to set a pointer to memory you don't own, with the exception of one past the end of an array, or one past the address of a scalar, or nullptr.
You can't add 10 to a pointer like that. One way to fix it would be to simply create Point2D's as a local variable:
Point2D p (5, 7);
Point2D q = p + 10;
q will now equal 15,17
That's assuming you create an operator+ that can take ints - your initializer_list one won't work here (because 10 isn't an initializer_list:
template<class T>
Point2D Point2D::operator+(T e)
{
x += e;
y += e;
return Point2D(x, y);
}

2D Global Array Error - Array Bound Is Not An Integer Constant

I can't seem to find an answer to this. I realize that the integer value used in an array must be known at compile time, and what I have here seems to meet that criteria. If I use:
int L = 50; // number of interior points in x and y
int pts = L + 2; // interior points + boundary points
double u[pts][pts], // potential to be found
u_new[pts][pts]; // new potential after each step
Then I get the array bound error, even though the value for pts is known at compile time. The code is accepted, however, when I use:
int L = 50; // number of interior points in x and y
int pts = L + 2; // interior points + boundary points
double u[52][52], // potential to be found
u_new[52][52]; // new potential after each step
Am I missing something here? If not, what can I do to have it accept pts?
When you use
int L = 50;
int pts = L + 2;
L and pts cannot be used as dimensions of arrays since they are not compile time constants. Use constexpr qualifiers to let the compiler know that they can be computed at compile time, and hence can be used as dimensions of arrays.
constexpr int L = 50;
constexpr int pts = L + 2;

Computing Rand error efficiently

I'm trying to compare two image segmentations to one another.
In order to do so, I transform each image into a vector of unsigned short values, and calculate the rand error,
according to the following formula:
where:
Here is my code (the rand error calculation part):
cv::Mat im1,im2;
//code for acquiring data for im1, im2
//code for copying im1(:)->v1, im2(:)->v2
int N = v1.size();
double a = 0;
double b = 0;
for (int i = 0; i <N; i++)
{
for (int j = 0; j < i; j++)
{
unsigned short l1 = v1[i];
unsigned short l2 = v1[j];
unsigned short gt1 = v2[i];
unsigned short gt2 = v2[j];
if (l1 == l2 && gt1 == gt2)
{
a++;
}
else if (l1 != l2 && gt1 != gt2)
{
b++;
}
}
}
double NPairs = (double)(N*N)/2;
double res = (a + b) / NPairs;
My problem is that length of each vector is 307,200.
Therefore the total number of iterations is 47,185,920,000.
It makes the running time of the entire process is very slow (a few minutes to compute).
Do you have any idea how can I improve it?
Thanks!
Let's assume that we have P distinct labels in the first image and Q distinct labels in the second image. The key observation for efficient computation of Rand error, also called Rand index, is that the number of distinct labels is usually much smaller than the number of pixels (i.e. P, Q << n).
Step 1
First, pre-compute the following auxiliary data:
the vector s1, with size P, such that s1[p] is the number of pixel positions i with v1[i] = p.
the vector s2, with size Q, such that s2[q] is the number of pixel positions i with v2[i] = q.
the matrix M, with size P x Q, such that M[p][q] is the number of pixel positions i with v1[i] = p and v2[i] = q.
The vectors s1, s2 and the matrix M can be computed by passing once through the input images, i.e. in O(n).
Step 2
Once s1, s2 and M are available, a and b can be computed efficiently:
This holds because each pair of pixels (i, j) that we are interested in has the property that both its pixels have the same label in image 1, i.e. v1[i] = v1[j] = p; and the same label in image 2, i.e. v2[i] = v2[ j ] = q. Since v1[i] = p and v2[i] = q, the pixel i will contribute to the bin M[p][q], and the same does the pixel j. Therefore, for each combination of labels p and q we need to consider the number of pairs of pixels that fall into the M[p][q] bin, and then to sum them up for all possible labels p and q.
Similarly, for b we have:
Here, we are counting how many pairs are formed with one of the pixels falling into the bin M[p][q]. Such a pixel can form a good pair with each pixel that is falling into a bin M[p'][q'], with the condition that p != p' and q != q'. Summing over all such M[p'][q'] is equivalent to subtracting from the sum over the entire matrix M (this sum is n) the sum on row p (i.e. s1[p]) and the sum on the column q (i.e. s2[q]). However, after subtracting the row and column sums, we have subtracted M[p][q] twice, and this is why it is added at the end of the expression above. Finally, this is divided by 2 because each pair was counted twice (once for each of its two constituent pixels as being part of a bin M[p][q] in the argument above).
The Rand error (Rand index) can now be computed as:
The overall complexity of this method is O(n) + O(PQ), with the first term usually being the dominant one.
After reading your comments, I tried the following approach:
calculate the intersections for each possible pair of values.
use the intersection results to calculate the error.
I performed the calculation straight on the cv::Mat objects, without converting them into std::vector objects. That gave me the ability to use opencv functions and achieve a faster runtime.
Code:
double a = 0, b = 0; //init variables
//unique function finds all the unique value of a matrix, with an optional input mask
std::set<unsigned short> m1Vals = unique(mat1);
for (unsigned short s1 : m1Vals)
{
cv::Mat mask1 = (mat1 == s1);
std::set<unsigned short> m2ValsInRoi = unique(mat2, mat1==s1);
for (unsigned short s2 : m2ValsInRoi)
{
cv::Mat mask2 = mat2 == s2;
cv::Mat andMask = mask1 & mask2;
double andVal = cv::countNonZero(andMask);
a += (andVal*(andVal - 1)) / 2;
b += ((double)cv::countNonZero(andMask) * (double)cv::countNonZero(~mask1 & ~mask2)) / 2;
}
}
double NPairs = (double)(N*(N-1)) / 2;
double res = (a + b) / NPairs;
The runtime is now reasonable (only a few milliseconds vs a few minutes), and the output is the same as the code above.
Example:
I ran the code on the following matrices:
//mat1 = [1 1 2]
cv::Mat mat1 = cv::Mat::ones(cv::Size(3, 1), CV_16U);
mat1.at<ushort>(cv::Point(2, 0)) = 2;
//mat2 = [1 2 1]
cv::Mat mat2 = cv::Mat::ones(cv::Size(3, 1), CV_16U);
mat2.at<ushort>(cv::Point(1, 0)) = 2;
In this case a = 0 (no matching pairs correspondence), and b=1(one matching pair for i=2,j=3). The algorithm result:
a = 0
b = 1
NPairs = 3
result = 0.3333333
Thank you all for your help!

Modifying a large dynamically sized 3D array mex/C++

Short Story: Trying to modify a large 3D array which gets allocated at run-time on the heap. I believe the function that modifies the array, vcross shown below, is creating memory that doesn't get destroyed.
Longer Story:
I have a large 3D double array (~126000x3x3 or about 8.6MB) that I need to run some operations on. I don't know how large the first dimension of this array is at compile time, so I allocate memory to the heap using the new and delete operations.
When I try to store values to this array, I get a segmentation violation. This makes me think that while storing values to the array, I'm creating memory somewhere that goes to waste, and eventually fills up the heap.
The code compiles fine, but hits a seg violation when I run it.
static void inpolyh(
double (*f)[3],//pointer to array[3], treated as 2D array where I don't know the first dimension until run-time.
double (*v)[3],
double (*p)[3],
size_t numF,
size_t numP)
{
/*Calculate the baseNormals*/
//allocate memory on the heap
double (*baseNormals)[3] = NULL;//pointer to an array[3]
if ( !(baseNormals = new double[numF][3]) ) { out_of_memory(); }
//store the vector cross products in each array[3] of baseNormals
for (int i=0; i<numF; i++) {
vcross(baseNormals[i],
v[(int)f[i][0]],
v[(int)f[i][1]],
v[(int)f[i][2]]);
//THIS WORKS
}
/*Calculate face normals of tetrahedron*/
//allocate memory on the heap (THIS WORKS)
double (*faceNormals)[3][3] = NULL; //pointer to an array[3] of arrays[3]
if ( !(faceNormals = new double[numP][3][3]) ) { out_of_memory(); }
//store vector cross products into each array[3] of faceNormals
for (int i=0; i<numP; i++ ) {
for (int j=0; j<3; j++ ) {
vcross(faceNormals[i][j],
p[i],
v[ (int) f[i][j] ],
v[ (int) f[i][ (j + 1) % 3 ] ] );
//SEG VIOLATION at i=37560
}
}
delete [] baseNormals;
delete [] faceNormals;
}
This is where I believe the culprit to be. I think this function creates memory somewhere that never gets destroyed. The vector cross product functions accepts four array[3] parameters and assigns some values to the first input parameter, which is passed by reference.
static void vcross(
double (&n)[3],
double a[3],
double b[3],
double c[3])
{
n[0] = b[1] * c[2] - a[1] * c[2] + a[1] * b[2] - b[2]
* c[1] + a[2] * c[1] - a[2] * b[1];
n[1] = b[2] * c[0] - a[2] * c[0] + a[2] * b[0] - b[0]
* c[2] + a[0] * c[2] - a[0] * b[2];
n[2] = b[0] * c[1] - a[0] * c[1] + a[0] * b[1] - b[1]
* c[0] + a[1] * c[0] - a[1] * b[0];
return;
}
Other details that may matter:
This is intended to be a mex function to run in matlab.
Default Encoding: windows-1252
MATLAB Root : C:\Program Files\MATLAB\R2012b
MATLAB Version : 8.0.0.783 (R2012b)
Operating System: Microsoft Windows 7
Processor ID : x86 Family 6 Model 58 Stepping 9, GenuineIntel
Virtual Machine : Java 1.6.0_17-b04 with Sun Microsystems Inc. Java HotSpot(TM) 64-Bit Server VM mixed mode
Window System : Version 6.1 (Build 7601: Service Pack 1)
Are you sure that (int)f[i][j] is always in the range [0, <dimension of v>)? The first thing I'd do is to print out the values of (int)f[i][j] when the loop runs. Or just fire a debugger to see the values at the moment of the crash.

How to map a 2D array in a 1D array in C++?

Lets say, I have a MxN arrays: int *b; and int **c; where
values in b are stored by columns (from c) and I need to put values
from c to b
values in b are stored by rows (from c) and I need to put values
from c to b
I know that basicly I would do it like that:
j = index / N;
i = index - (j * M);
in order to convert a 1D index into a 2D co-ordinate but have a problem
how to implement those 2 cases, 1) and 2)?
Let W be the width of the 2D array, and H its height. Then assuming row-major layout, the 1D index 'ix' relates to the 2D-index [x,y] as such:
ix = y*w + x;
y = ix / w; // implicit floor
x = ix % w;
e.g.:
const int W = 3, H=2;
int m[H][W] = {{1,2,3}, {4,5,6}};
int* oneD = &m[0][0];
assert(oneD[1*W + 2] == m[1][2]); // element 6, y=1, x=2