Memory comparison, which is faster? - c++

I have a 3D vector class. The private variables are defined:
union {
struct {
double x;
double y;
double z;
};
double data[3];
};
In implementing operator==, which is faster?
return this->x == v.x && this->y == v.y && this->z == v.z;
OR
return memcmp(this->data, v.data) == 0;

Unfortunately the two aren't equivalent. (Specifically NaNs and signed zeros don't use bitwise comparison inside the FPU).
So you should make your choice based on correctness, not speed.

Related

Why my compare operator is not comparing my point length and double value?

I create new operator to compare my point vector length and double value. I have condition to tolerate different which is less than 0.01.
When i using this operator to compare my Point and my double value (both values after approaching are same) but the operator == is not returning true.
class Point {
private:
double x, y, z;
public:
Point() { x = y = z = 0.0; }
Point(double v) { x = y = z = v; }
Point(double x, double y, double z){
this->x = x; this->y = y; this->z = z;
}
double getLength(){
return sqrt(pow(x,2)+pow(y,2)+pow(z,2));
}
friend const bool operator== (double &d, Point &v);
};
double approach(double num){
return floor(num*100)/100;
}
const bool operator== (const double &d, Point &v){
return (approach(d) == approach(v.getLength()));
}
int main()
{
Point p1(3,4,1);
cout << p1.getLength() << endl; // 5.09902
cout << approach(p1.getLength()) << endl;
cout << approach(5.091) << endl;
if(5.091 == p1)
cout << "True";
return 0;
}
This issue can be reproduced on gcc with 32 bit Intel architecture, without optimization.
Here is an example of it happening:
compiler explorer example.
This is due to the infamous 323 bug of gcc, which struggles to work with Intel's 80 bit floating point registers, which are wider than the 64 bits of type double. Some of the values end up in the 80-bit register, and some values in the 64-bit memory value.
In your case, approach(d) is called first, and then get spilled to memory when v.getLength() is called. The value of approach(v.getLength()), on the other hand, is not getting spilled and gets all of register's 80-bit precision.
When you compare an 80-bit accurate value, and a truncated 64-bit value, the comparison result is false.
A possible solution is to avoid the division by 100 in approach(), since it is what introduces the extra bits. Instead, you can try:
static constexpr double magnitude = 100.0;
const bool operator== (double d, const Point &v){
return floor(d * magnitude) == floor(v.getLength() * magnitude));
}

Is that possible to give floating values to the clipper Paths

Clipper takes integer input but I want to pass floating values without losing the precision.
Clipper struct for Integer and double value.
struct IntPoint {
cInt X;
cInt Y;
#ifdef use_xyz
cInt Z;
IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
#else
IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
#endif
friend inline bool operator== (const IntPoint& a, const IntPoint& b)
{
return a.X == b.X && a.Y == b.Y;
}
friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
{
return a.X != b.X || a.Y != b.Y;
}
};
struct DoublePoint
{
double X;
double Y;
DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
};
why it is not taking the double value as an input.
Paths Polygon(2);
Polygon[0] << IntPoint(10, 10) << IntPoint(60, 10) << IntPoint(30, 100) ;
Polygon[1] << IntPoint(20, 20) << IntPoint(50, 20) << IntPoint(30, 80) ; //it Works
Paths Line(1);
line[0] << DoublePoint(40.2, 10.2) << DoublePoint(56.5, 85.45); //Not works
Clipper only uses integer point types.
The IntPoint structure is used to represent all vertices in the Clipper Library. An integer storage type has been deliberately chosen to preserve numerical robustness. (Early versions of the library used floating point coordinates, but it became apparent that floating point imprecision would always cause occasional errors.) [src]
You can however scale your input coordinates by a desirable factor.
So instead of wanting this, (which doesn't exist)
line[0] << DoublePoint(40.2, 10.2) << DoublePoint(56.5, 85.45); //Not works
You can scale by 100.
line[0] << IntPoint(4020, 1020) << IntPoint(5650, 8545); //works
Just remember to scale output coordinates by 0.01 to get back to your coordinate system.

User defined calculation on structs/classes

I was once using Unity and they use a cool System to add and multiply vectors.
This is a short excerpt from the Reference (http://docs.unity3d.com/ScriptReference/Transform.html)
foreach (Transform child in transform) {
child.position += Vector3.up * 10.0F;
}
as you can see they can just add and multiply two Vectors (structs/classes) even though they could have different variables. Right now when I try to make such a calculation I have to add the x and y of a 2d float vector individually.
So how can i add structs like a
struct Vec2f{
float x;
float y;
};
together by writing
Vec2f c = a + b;
instead of
c.x = a.x + b.x;
c.y = a.y + b.y;
EDIT:
You need to overload operators like '+', '-' etc. in your struct. Example for addition:
struct Vec2f
{
float x;
float y;
Vec2f operator+(const Vec2f& other) const
{
Vec2f result;
result.x = x + other.x;
result.y = y + other.y;
return result;
}
};
EDIT 2:
RIJIK asks in comment:
Also i wonder if there are some tricks to make the functions not to be so repetetive. I mean if i now want to use an operator i have to make a function for each operator even if there is no big difference between the functions besides the operator which is used. How do you approach in implementing calculations or many operators?
So one thing you can do is use another operators in operator. Something like you can change subtraction to addition, by simply negate second number:
a - b becomes a + (-b)
Of course you need negation operator first in your struct to do that. Example code:
struct Vec2f
{
float x;
float y;
Vec2f operator+(const Vec2f& other) const
{
Vec2f result;
result.x = x + other.x;
result.y = y + other.y;
return result;
}
Vec2f operator-() const
{
Vec2f result;
result.x = -x;
result.y = -y;
return result;
}
// we use two operators from above to define this
Vec2f operator-(const Vec2f& other) const
{
return (*this + (-other));
}
};
One nice thing about this is that if you change addition for example than you don't need to change subtraction. It is changed automatically.
And as reply to this:
But i don't understand why i should make the functions constant.
Because then you can use this function with constant variables. For example:
const Vec2f screenSize = { 800.0f, 600.0f };
const Vec2f boxSize = { 100.0f, 200.0f };
const Vec2f sub = screenSize - boxSize;
I am using here also curly braces initialization, cause you don't define any constructor.

c++ overloading plus in an efficient way

I wrote a class like this:
class vector3D{
public:
double x,y,z;
}
and i overload + operator:
class vector3D{
public:
double x,y,z;
vector3D operator+(const vector3D &lhs)
{
vector3D temp(x+lhs.x,y+lhs.y,z+lhs.z);
return temp;
}
}
but using C=A+B is slower than
C.x = A.x + B.x;
C.y = A.y + B.y;
C.z = A.z + B.z;
i think it is because defining a vector3D instance in + overloading function. is there anyway to avoid this?
(FYI: i build with this flags: -Wall -Wextra -Wunreachable-code -m32 -DNDEBUG -O2 -D_LARGEFILE64_SOURCE -D_REETRANT -D_THREAD_SAFE)
EDIT:
this is how i test speed of two approach(in main() ):
//test bench
vector3D A(0.0,0.0,0.0), B(1e-9,1e-9,1e-9);
clock_t c = clock();
//case A
for(long int i=0;i<1000000000;i++)
{
A = A + B;
}
cout<<"case A took: "<<1.0*(clock()-c)/CLOCKS_PER_SEC<<A<<endl;
c = clock();
//case B
for(long int i=0;i<1000000000;i++)
{
A._x = A._x+B._x;
A._y = A._x+B._y;
A._z = A._x+B._z;
}
cout<<"case B took: "<<1.0*(clock()-c)/CLOCKS_PER_SEC<<A<<endl;
and the result is:
case A took: 5.539[1, 1, 1]
case B took: 1.531[2, 2, 2]
Since you're creating an additional object, it will carry some overhead. This is inherent.
However, looking at the "payload lines" you want, they are very similar to what you'd have in the body of operator+= adding some other:
vector3D &operator+=(const vector3D &other) // Note - no objects created.
{
x += other.x;
y += other.y;
z += other.z;
return *this; // Note - return by reference.
}
Of course, operator+= modifies its left operand (which is exactly why you have operator+ with its object-creation overhead).
In general, you should prefer operator+= for heavy objects where it is applicable (see also this question).
You may actually get a performance boost by collapsing this to one line and taking advantage of return value optimization:
vector3D operator+(const vector3D &lhs)
{
return vector3D(x+lhs.x,y+lhs.y,z+lhs.z);
}

Find all points of a grid within a circle, ordered by norm

How would you solve the problem of finding the points of a (integer) grid within a circle centered on the origin of the axis, with the results ordered by norm, as in distance from the centre, in C++?
I wrote an implementation that works (yeah, I know, it is extremely inefficient, but for my problem anything more would be overkill). I'm extremely new to C++, so my biggest problem was finding a data structure capable of
being sort-able;
being able to save an array in one of its elements,
rather than the implementation of the algorithm. My code is as follows. Thanks in advance, everyone!
typedef std::pair<int, int[2]> norm_vec2d;
bool norm_vec2d_cmp (norm_vec2d a, norm_vec2d b)
{
bool bo;
bo = (a.first < b.first ? true: false);
return bo;
}
int energy_to_momenta_2D (int energy, std::list<norm_vec2d> *momenta)
{
int i, j, norm, n=0;
int energy_root = (int) std::sqrt(energy);
norm_vec2d temp;
for (i=-energy_root; i<=energy_root; i++)
{
for (j =-energy_root; j<=energy_root; j++)
{
norm = i*i + j*j;
if (norm <= energy)
{
temp.first = norm;
temp.second[0] = i;
temp.second[1] = j;
(*momenta).push_back (temp);
n++;
}
}
}
(*momenta).sort(norm_vec2d_cmp);
return n;
}
How would you solve the problem of finding the points of a (integer) grid within a circle centered on the origin of the axis, with the results ordered by norm, as in distance from the centre, in C++?
I wouldn't use a std::pair to hold the points. I'd create my own more descriptive type.
struct Point {
int x;
int y;
int square() const { return x*x + y*y; }
Point(int x = 0, int y = 0)
: x(x), y(y) {}
bool operator<(const Point& pt) const {
if( square() < pt.square() )
return true;
if( pt.square() < square() )
return false;
if( x < pt.x )
return true;
if( pt.x < x)
return false;
return y < pt.y;
}
friend std::ostream& operator<<(std::ostream& os, const Point& pt) {
return os << "(" << pt.x << "," << pt.y << ")";
}
};
This data structure is (probably) exactly the same size as two ints, it is less-than comparable, it is assignable, and it is easily printable.
The algorithm walks through all of the valid points that satisfy x=[0,radius] && y=[0,x] && (x,y) inside circle:
std::set<Point>
GetListOfPointsInsideCircle(double radius = 1) {
std::set<Point> result;
// Only examine bottom half of quadrant 1, then
// apply symmetry 8 ways
for(Point pt(0,0); pt.x <= radius; pt.x++, pt.y = 0) {
for(; pt.y <= pt.x && pt.square()<=radius*radius; pt.y++) {
result.insert(pt);
result.insert(Point(-pt.x, pt.y));
result.insert(Point(pt.x, -pt.y));
result.insert(Point(-pt.x, -pt.y));
result.insert(Point(pt.y, pt.x));
result.insert(Point(-pt.y, pt.x));
result.insert(Point(pt.y, -pt.x));
result.insert(Point(-pt.y, -pt.x));
}
}
return result;
}
I chose a std::set to hold the data for two reasons:
It is stored is sorted order, so I don't have to std::sort it, and
It rejects duplicates, so I don't have to worry about points whose reflection are identical
Finally, using this algorithm is dead simple:
int main () {
std::set<Point> vp = GetListOfPointsInsideCircle(2);
std::copy(vp.begin(), vp.end(),
std::ostream_iterator<Point>(std::cout, "\n"));
}
It's always worth it to add a point class for such geometric problem, since usually you have more than one to solve. But I don't think it's a good idea to overload the 'less' operator to satisfy the first need encountered. Because:
Specifying the comparator where you sort will make it clear what order you want there.
Specifying the comparator will allow to easily change it without affecting your generic point class.
Distance to origin is not a bad order, but for a grid but it's probably better to use row and columns (sort by x first then y).
Such comparator is slower and will thus slow any other set of points where you don't even care about norm.
Anyway, here is a simple solution using a specific comparator and trying to optimize a bit:
struct v2i{
int x,y;
v2i(int px, int py) : x(px), y(py) {}
int norm() const {return x*x+y*y;}
};
bool r_comp(const v2i& a, const v2i& b)
{ return a.norm() < b.norm(); }
std::vector<v2i> result;
for(int x = -r; x <= r; ++x) {
int my = r*r - x*x;
for(int y = 0; y*y <= my; ++y) {
result.push_back(v2i(x,y));
if(y > 0)
result.push_back(v2i(x,-y));
}
}
std::sort(result.begin(), result.end(), r_comp);