I'm trying to implement Closest pair of points in C++ according to Cormen book and wikipedia article, I think that algorithm is correct, but it does work only for a very small data. Code is below:
#include <cstdio>
#include <algorithm>
#include <cmath>
#define REP(i,n) for(int i=0;i<n;i++)
using namespace std;
struct point
{
long long x, y;
};
struct dist
{
long long x_1,y_1,x_2,y_2, distance;
} dis;
inline bool OrdX(const point &a, const point &b)
{
if(a.x==b.x)
{
return a.y<b.y;
}
return a.x<b.x;
}
inline int OrdY(const point &a, const point &b)
{
if(a.y==b.y)
{
return a.x<b.x;
}
return a.y<b.y;
}
// is - function that check is a an element of X_L array
inline bool is(const point &a, point *X_L, int p, int k)
{
if(p<=k)
{
int center = (p+k)/2;
if(X_L[center].x == a.x)
{
return true;
}
if(X_L[center].x > a.x)
{
return is(a, X_L, p, center-1);
}
else
{
return is(a, X_L, center+1, k);
}
}
return false;
}
// odl - function takes two points and return distance between them ^2
inline long long odl(const point &a, const point &b)
{
return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));
}
int tmp;
// fun - function that returns the pair of closest points using divide & conquer
struct dist fun(int n, point *X, point *Y)
{
// if there are less that 4 points - it checks it using bruteforce
if(n<4)
{
if(odl(X[0], X[1]) < dis.distance)
{
dis.distance = odl(X[0],X[1]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[1].x;
dis.y_2 = X[1].y;
}
if(n==3)
{
if(odl(X[0], X[2]) < dis.distance)
{
dis.distance = odl(X[0],X[2]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[2].x;
dis.y_2 = X[2].y;
}
if(odl(X[1], X[2]) < dis.distance)
{
dis.distance = odl(X[1],X[2]);
dis.x_1 = X[1].x;
dis.y_1 = X[1].y;
dis.x_2 = X[2].x;
dis.y_2 = X[2].y;
}
}
}
// otherwise it divides points into two arrays and runs fun
// recursively foreach part
else
{
int p=n/2;
int PPP = (X[p].x + X[p-1].x)/2;
point *X_L = new point[p];
point *X_R = new point[n-p];
point *Y_L = new point[p];
point *Y_R = new point[n-p];
REP(i,p)
X_L[i] = X[i];
for(int r=p; r<n; r++)
{
X_R[r-p] = X[r];
}
int length_Y_L = 0;
int length_Y_R = 0;
REP(i,n)
{
if(is(Y[i], X_L, 0, p))
{
Y_L[length_Y_L++] = Y[i];
}
else
{
Y_R[length_Y_R++] = Y[i];
}
}
dist D_L = fun(p, X_L, Y_L);
dist D_R = fun(n-p, X_R, Y_R);
dist D;
if(D_L.distance < D_R.distance)
{
D = D_L;
}
else
{
D = D_R;
}
tmp = 0;
point *Y2 = new point[n];
double from = sqrt((double)D.distance);
for(int r=0; r<n; r++)
{
if(Y[r].x > (long long)PPP-from && Y[r].x < (long long)PPP + from)
{
Y2[tmp++] = Y[r];
}
}
//--tmp;
//int xxx = min(7, tmp-r);
int r = 0;
for(int j=1; j<min(7, tmp-r); j++)
{
if(odl(Y2[r], Y2[r+j]) < D.distance)
{
D.distance = odl(Y2[r], Y2[r+j]);
D.x_1 = Y2[r].x;
D.y_1 = Y2[r].y;
D.x_2 = Y2[r+j].x;
D.y_2 = Y2[r+j].y;
}
r++;
}
dis = D;
}
return dis;
}
int main()
{
int n;
n = 7;
point *X = new point[n];
point *Y = new point[n];
for(int i=0; i< 7; i++)
{
X[i].x = 0;
X[i].y = 10*i;
}
/*
REP(i,n)
{
scanf("%lld %lld", &X[i].x, &X[i].y);
}
*/
sort(X, X+n, OrdX);
REP(i,n)
Y[i] = X[i];
sort(Y, Y+n, OrdY);
dis.distance = odl(X[0], X[1]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[1].x;
dis.y_2 = X[1].y;
dist wynik = fun(n, X, Y);
printf(" %lld %lld\n %lld %lld\n", wynik.x_1, wynik.y_1, wynik.x_2, wynik.y_2);
return 0;
}
and I get this error:
malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char
*) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct
malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size)
>= (unsigned long)((((__builtin_offsetof (struct malloc_chunk,
fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t)))
- 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end &
pagemask) == 0)' failed.
I've tried loooking for explanation of this error but can't find anything clear for me :/.
Can You please help me to solve this ? Thanks
The message means you've done something bad with dynamically allocated memory. Perhaps you freed an object twice, or wrote into memory beyond the beginning or end of an array-like dynamically allocated object.
On Linux, the tool valgrind may help pin-point the first place in your program's execution where it made a boo-boo.
By the way, your macro:
#define REP(i,n) for(int i=0;i<n;i++)
is poorly defined. The substitution of n should be parenthesized, because n could be an expression which has the wrong precedence with respect to the < operator. For instance: REP(i, k < m ? z : w). You want:
#define REP(var,n) for(int var=0;var<(n);var++)
The var reminds the programmer that this argument is a variable name, and not an arbitrary expression.
Your function is is redundant; that's just std::binary_search. That would help a lot with #sbi's problem of readability.
There's also quite a bit of redundancy in blocks like
dis.distance = odl(X[0],X[1]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[1].x;
dis.y_2 = X[1].y;
You can write a simple function dist calcDist(point,point) for this. You should probably move all the point definitions and associated functions to a separate header "point.h", again to keep things readable.
As for the memory issue: first, the arrays X_L and X_R are not really necessary. They contain the same data as X, so you can make them pointers to &(X[0]) and &(X[p) respectively. Y_L and Y_R are shuffled versions, so you do need to the arrays to copy data to. However, if you allocate them with new[], you are responsible for cleanup with delete[]. It looks like you can just use a std::vector<point> Y_L instead. No need to do bookkeeping, vector does that for you. Just call Y_L.push_back(Y[i]).
Related
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.
I need to find the minimum of five float values, excluding any zero, and its location in the order.
The amount of data, which is going to use this piece of code is going to huge and needs fast processing. this is going to be in a server, which processes inputs 24*7. the minimum value must get updated in the DB, eventually.
Which would of the following be faster in terms of memory and time usage, or if there is any other simpler way, do let me know.
Specialize std::max with tuple. have four tuple values
indicating <value,location>.
example,
std::tuple<float,int> f1 (10,1);
bool less(float x, float y)
{
if (x!=0 && x < y)
return 0;
else return 1;
}
tuple min (std::initializer_list<tuple> il, bool comp){
what do I do here for initializer list?
}
int main () {
out << get<1>(min({f1,f2,f3,f4,f5},less));
}
Use std::min_element and overload the less operator as above?
would this not be an overkill using an iterator for float?
Two simple alternatives are:
#include <utility>
std::pair<float, unsigned char> my_min(float *a) {
float val = a[0];
unsigned char pos = 0;
for (unsigned char i = 0; i < 5; ++i) {
if (a[i] != 0 && (a[i] < val || val == 0)) {
val = a[i];
pos = i;
}
}
return {val, pos};
}
int main() {
float a[5] = {1, 4, 0.5, 0, 5};
return my_min(a).second;
}
and
#include <utility>
std::pair<float, unsigned char> my_min(float *a) {
float val = a[0];
unsigned char pos = 0;
float *end = a + 5;
for (float *ip = a; ip < end; ++ip) {
float i = *ip;
if (i != 0 && (i < val || val == 0)) {
val = i;
pos = ip - a;
}
}
return {val, pos};
}
int main() {
float a[5] = {1, 4, 0.5, 0, 5};
return my_min(a).second;
}
I have written a compare-function that should compare two possible move options for a player in a game that works like Chess. Each Move contains a Figure that should do the move and a Point, where it will move. The Points are already checked, so all of them are valid moves. When I try to sort a list containing all of the moves currently available using strict weak ordering and the std::sort function, I get a SIGSEG after my compare function got confrontet with some garbage Figure Pointer in one Move.
I already tried to figure out where the garbage pointer came from, but ony found, that the std::sort function somehow put it in the mix of all the other moves. The same seg fault occurs when i try to sort with std::stable_sort. I also thougt about stack issues due to the fact, that I had some before, but this isn't the case either.
bool cmpWhite(White_Move m1, White_Move m2) {
if (m1.f == nullptr) {
return true;
} else if (m2.f == nullptr) {
return true;
}
int sum1 = 0;
double avg1 = 0;
Figure *f1 = m1.f;
Point origin1 = f1->getCoordinatesAsPoint();
int sum2 = 0;
double avg2 = 0;
Figure *f2 = m2.f;
Point origin2 = f2->getCoordinatesAsPoint();
Point p;
movePiece(field_pub, f1, m1.p);
std::vector<Point> moves = black_king->getAllNewPossiblePositions();
for (int i = 0; i < moves.size(); i++) {
p = moves[i];
if (!black_king->isPositionBlocked(field_pub, p.x, p.y)) {
sum1++;
// avg1 += sqrt((p.x - target_pub.x) * (p.x - target_pub.x) + (p.y - target_pub.y) * (p.y - target_pub.y));
}
}
p = black_king->getCoordinatesAsPoint();
if (!black_king->isPositionBlocked(field_pub, p.x, p.y)) {
sum1++;
}
// avg1 = (double)sum1;
movePiece(field_pub, f1, origin1);
movePiece(field_pub, f2, m2.p);
moves = black_king->getAllNewPossiblePositions();
for (int i = 0; i < moves.size(); i++) {
p = moves[i];
if (!black_king->isPositionBlocked(field_pub, p.x, p.y)) {
sum2++;
// avg2 += sqrt((p.x - target_pub.x) * (p.x - target_pub.x) + (p.y - target_pub.y) * (p.y - target_pub.y));
}
}
p = black_king->getCoordinatesAsPoint();
if (!black_king->isPositionBlocked(field_pub, p.x, p.y)) {
sum2++;
}
// avg2 = (double)sum2;
movePiece(field_pub, f2, origin2);
std::cout << "cmp: " << sum1 << " " << sum2 << std::endl;
return sum1 < sum2;
}
std::vector<White_Move> sortBestMovesForWhite(Figure **figures, int size, King *bKing, int **field, Point target) {
target_pub = target;
field_pub = new int *[FIELD_WIDTH];
for (int x = 0; x < FIELD_WIDTH; x++) {
field_pub[x] = new int[FIELD_HEIGHT];
for (int y = 0; y < FIELD_HEIGHT; y++) {
field_pub[x][y] = field[x][y];
}
}
black_king = bKing;
std::vector<White_Move> moves;
for (int i = 0; i < size; i++) {
Figure *f = figures[i];
std::vector<Point> m_point = f->getAllNewPossiblePositions();
for (int j = 0; j < m_point.size(); j++) {
if (!f->isPositionBlocked(field, m_point.at(j).x, m_point.at(j).y)) {
White_Move move = {f, m_point.at(j)};
moves.push_back(move);
}
}
}
// std::stable_sort(moves.begin(), moves.end(), cmpWhite);
std::sort(moves.begin(), moves.end(), cmpWhite);
for (int x = 0; x < FIELD_WIDTH; x++) {
delete[] field_pub[x];
}
delete[] field_pub;
return moves;
}
One of your return true at the start of your compare function should be return false. The comparator for std::sort must meet the conditions specified here: https://en.cppreference.com/w/cpp/named_req/Compare. If this is not the case std::sort will have undefined behaviour.
The correct implementation should look something like:
bool cmpWhite(White_Move m1, White_Move m2) {
if (m1.f == nullptr) {
return m2.f != nullptr;
}
if (m2.f == nullptr) {
return false;
}
...
}
I would like to pass a character array micPointsChar[] to a function initMicPoints() and parse it into a multi-dimensional array micPoints. I am able to successfully do this using a one dimensional array:
char micPointsChar[30 + 1] = {};
float *initMicPoints(char micPointsChar[], float micPoints[3]);
int main()
{
// Read in mic points from file
char micPointsChar[40] = "2,3.343,4.432\n";
float micPoints[3] = {};
float *newMicPoints = initMicPoints(micPointsChar, micPoints);
for (int i = 1; i <= 3; i++)
{
Serial.print(newMicPoints[i]);
Serial.print("\n");
}
return 0;
}
float *initMicPoints(char micPointsChar[], float micPoints[3])
{
static int i = 1;
static int micNum = 1;
static int numMics = 1;
float coordinateDec = 0;
char *coordinate = strtok(micPointsChar, ",\n");
coordinateDec = atof(coordinate);
while (micNum <= numMics)
{
while (i <= ((micNum * 3)) && (coordinate != NULL))
{
if (i == ((micNum * 3) - 2))
{
micPoints[1] = coordinateDec;
}
else if (i == ((micNum * 3) - 1))
{
micPoints[2] = coordinateDec;
}
else if (i == ((micNum * 3) - 0))
{
micPoints[3] = coordinateDec;
}
coordinate = strtok(NULL, ",\n");
coordinateDec = atof(coordinate);
i++;
}
micNum++;
}
return micPoints;
}
This outputs the expected:
2.00
3.34
4.43
However, when I change my code to handle a multidimensional array, micPoints[360][3]:
char micPointsChar[30 + 1] = {};
float *initMicPoints(char micPointsChar[], float micPoints[360][3]);
int main()
{
// Read in mic points from file
char micPointsChar[40] = "2,3.343,4.432\n";
float micPoints[360][3] = {};
float *newMicPoints = initMicPoints(micPointsChar, micPoints);
static int i = 0;
for (i = 1; i <= 3; i++)
{
Serial.print(*newMicPoints[i][0]);
Serial.print("\n");
Serial.print(*newMicPoints[i][1]);
Serial.print("\n");
Serial.print(*newMicPoints[i][2]);
Serial.print("\n");
}
return 0;
}
float *initMicPoints(char micPointsChar[], float micPoints[360][3])
{
static int i = 1;
static int micNum = 1;
static int numMics = 1;
float coordinateDec = 0;
char *coordinate = strtok(micPointsChar, ",\n");
coordinateDec = atof(coordinate);
while (micNum <= numMics)
{
while (i <= ((micNum * 3)) && (coordinate != NULL))
{
if (i == ((micNum * 3) - 2))
{
micPoints[i][0] = coordinateDec;
}
else if (i == ((micNum * 3) - 1))
{
micPoints[i][1] = coordinateDec;
}
else if (i == ((micNum * 3) - 0))
{
micPoints[i][2] = coordinateDec;
}
coordinate = strtok(NULL, ",\n");
coordinateDec = atof(coordinate);
i++;
}
micNum++;
}
return micPoints;
}
I receive a compile time error of:
cannot convert 'float (*)[3]' to 'float*' in return
Am I making this too complicated? What is the best way to return a multidimensional array?
Firstly, unfortunately
float *initMicPoints(char micPointsChar[], float micPoints[360][3])
is seen as
float *initMicPoints(char* micPointsChar, float (*micPoints)[3])
you may pass by reference to keep the size:
float *initMicPoints(char* micPointsChar, float (&micPoints)[360][3])
Then as you return micPoints
return type should be float (&)[360][3] or float (&)[360][3]
which give an ugly
float (&initMicPoints(char* micPointsChar, float (&micPoints)[360][3]))[360][3]
and at the call site:
float (&newMicPoints)[360][3] = initMicPoints(micPointsChar, micPoints);
Prefer std::array or std::vector with cleaner syntax.
In both cases you are just returning the parameter. So this return value is redundant. Instead, avoid the problem by returning void:
void initMicPoints(char micPointsChar[], float micPoints[360][3])
The calling code would look like:
float micPoints[360][3] = {};
initMicPoints(micPointsChar, micPoints);
for (int i = 1; i <= 3; i++)
{
Serial.print(micPoints[i][0]);
Serial.print("\n");
etc. You could make another variable float (*newMicPoints)[3] = micPoints; if you want but this would also be redundant.
There is little point in returning the array, because your function hasn't constructed it. You're just giving the caller a copy of the argument value.
A few traditional functions in the standard C library do this, like strcpy. I can't remember the last time I saw a piece of code which used the return value of strcpy, which is just the destination pointer that was passed in.
// redeclare and redefine to return nothing!
void initMicPoints(char micPointsChar[], float micPoints[3]);
int main()
{
// Read in mic points from file
char micPointsChar[40] = "2,3.343,4.432\n";
float micPoints[3] = {};
initMicPoints(micPointsChar, micPoints);
for (int i = 1; i <= 3; i++)
{
Serial.print(micPoints[i]); // refer to original array, now initialized
Serial.print("\n");
}
return 0;
}
Fact is that initMicPoints clobbers the array that is passed in, which is why you called it init. There is little use in capturing a pointer, and then ignoring the original array that you have in scope. That just dresses up imperative code to look functional, without the underlying semantics.
In the above code we can turn the array two dimensional, without the return value type issue cropping up; we eliminated it.
I am trying to speed up a piece of code that is ran a total of 150,000,000 times.
I have analysed it using "Very Sleepy", which has indicated that the code is spending the most time in these 3 areas, shown in the image:
The code is as follows:
double nonLocalAtPixel(int ymax, int xmax, int y, int x , vector<nodeStructure> &nodeMST, int squareDimension, Mat &inputImage) {
vector<double> nodeWeights(8,0);
vector<double> nodeIntensities(8,0);
bool allZeroWeights = true;
int numberEitherside = (squareDimension - 1) / 2;
int index = 0;
for (int j = y - numberEitherside; j < y + numberEitherside + 1; j++) {
for (int i = x - numberEitherside; i < x + numberEitherside + 1; i++) {
// out of range or the centre pixel
if (j<0 || i<0 || j>ymax || i>xmax || (j == y && i == x)) {
index++;
continue;
}
else {
int centreNodeIndex = y*(xmax+1) + x;
int thisNodeIndex = j*(xmax+1) + i;
// add to intensity list
Scalar pixelIntensityScalar = inputImage.at<uchar>(j, i);
nodeIntensities[index] = ((double)*pixelIntensityScalar.val);
// find weight from p to q
float weight = findWeight(nodeMST, thisNodeIndex, centreNodeIndex);
if (weight!=0 && allZeroWeights) {
allZeroWeights = false;
}
nodeWeights[index] = (weight);
index++;
}
}
}
// find min b
int minb = -1;
int bCost = -1;
if (allZeroWeights) {
return 0;
}
else {
// iteratate all b values
for (int i = 0; i < nodeWeights.size(); i++) {
if (nodeWeights[i]==0) {
continue;
}
double thisbCost = nonLocalWithb(nodeIntensities[i], nodeIntensities, nodeWeights);
if (bCost<0 || thisbCost<bCost) {
bCost = thisbCost;
minb = nodeIntensities[i];
}
}
}
return minb;
}
Firstly, I assume the spent time indicated by Very Sleepy means that the majority of time is spent allocating the vector and deleting the vector?
Secondly, are there any suggestions to speed this code up?
Thanks
use std::array
reuse the vectors by passing it as an argument of the function or a global variable if possible (not aware of the structure of the code so I need more infos)
allocate one 16 vector size instead of two vectors of size 8. Will make your memory less fragmented
use parallelism if findWeight is thread safe (you need to provide more details on that too)