How to simplify logical operation in C - conditional-statements

I have this following logic which needs simplifing to look clearer and consise:
if (x1 < y1)
return 1;
else if (x1 == y1)) {
if (x2 < y2)
return 1;
else if (x2 == y2) {
if (x3 < y3)
return 1;
} else
return 0;
}
} else
return 0;
In order to solve this above problem, I have applied logical expressions to further simplify these few lines of conditions:
if (x1 < y1 || (x1 == y1 && x2 < y2) || (x1 == y1 && x2 == y2 && x3 < y3))
return 1;
else
return 0;
I am not sure how to simplify further from here. Can anyone help me?
Update:
For further simplifying, I tried applying boolean algebra to this expression, but no luck! I have come up with this:
A + (A1 * B) + (A1 * B1 * C)
Where A denotes to x1 < y1 and A1 denotes to x1 == y2

IMO the cleanest way to do this sort of chained relation in C is with ?::
return x1 == y1 ? x2 == y2 ? x3 < y3 : x2 < y2 : x1 < y1;
As noted in the question comments, if you really care about performance, and the values have limited range, you can use bit twiddling to combine them into a single value for comparison. If the fields are all uint16_t (unsigned 16-bit values), for example, you can do:
uint64_t x = ((uint64_t)x1 << 32) + ((uint64_t)x2 << 16) + x3;
uint64_t y = ((uint64_t)y1 << 32) + ((uint64_t)y2 << 16) + y3;
return x < y;
but this is probably less clear and probably a premature optimization.

Related

how to calculate the angle of a line form by two points from the north direction?

Does anyone have a script/code/function to calculate the angle from the north line (bearing) of a line formed by two points (x1,y1) and (x2,y2)?
Two points (x1,y1) and (x2,y2)
In javascript
function calcAngleDegrees(x1, y1,x2,y2) {
let x = x2 - x1 ;
let y = y2 - y1 ;
return Math.atan2(y, x) * 180 / Math.PI;
}
let angleDegree = calcAngleDegrees(0,0,5,-5); // -45
let bearingFromAngle = (450 - angleDegree ) % 360; // 135
float calc_azimuth(float x1, float y1, float x2, float y2)
{
//calculate deltas
float deltax = x2 - x1;
float deltay = y2 - y1;
//chech if the deltas are zeros, and if they are, then use a small number
if (deltax == 0.0)
deltax = 0.000001;
if (deltay == 0.0)
deltay = 0.000001;
//Calculate angle
float angle = abs(atan(deltay / deltax) * (180/3.14159));
//define and initialize azimuth
float azim = 0;
//first quadrant
if (x2 >= x1 && y2 > y1)
azim = 90.0 - angle;
//second quadrant
else if (x2 > x1 && y2 <= y1)
azim = angle + 90.0;
//third quadrant
else if (x2 <= x1 && y2 < y1)
azim = 270.0 - angle;
//fourth quadrant
else
azim = 270.0 + angle;
return azim;
}

Quaternion addition like 3ds/gmax does with it's quats

A project I'm working on needs a function which mimics 3ds/gmax's quaternion addition. A test case of (quat 1 2 3 4)+(quat 3 5 7 9) should equal (quat 20 40 54 2). These quats are in xyzw.
So, I figure it's basic algebra, given the clean numbers. It's got to be something like this multiply function, since it doesn't involve sin/cos:
const quaternion &operator *=(const quaternion &q)
{
float x= v.x, y= v.y, z= v.z, sn= s*q.s - v*q.v;
v.x= y*q.v.z - z*q.v.y + s*q.v.x + x*q.s;
v.y= z*q.v.x - x*q.v.z + s*q.v.y + y*q.s;
v.z= x*q.v.y - y*q.v.x + s*q.v.z + z*q.s;
s= sn;
return *this;
}
source
But, I don't understand how sn= s*q.s - v*q.v is supposed to work. s is a float, v is vector. Multiply vectors and add to float?
I'm not even sure which terms of direction/rotation/orientation these values represent, but if the function satisfies the quat values above, it'll work.
Found it. Turns out to be known as multiplication. Addition is multiplication. Up is sideways. Not confusing at all :/
fn qAdd q1 q2 = (
x1=q1.x
y1=q1.y
z1=q1.z
w1=q1.w
x2=q2.x
y2=q2.y
z2=q2.z
w2=q2.w
W = (W1 * W2) - (X1 * X2) - (Y1 * Y2) - (Z1 * Z2)
X = (W1 * X2) + (X1 * W2) + (Y1 * Z2) - (Z1 * Y2)
Y = (W1 * Y2) + (Y1 * W2) + (Z1 * X2) - (X1 * Z2)
Z = (W1 * Z2) + (Z1 * W2) + (X1 * Y2) - (Y1 * X2)
return (quat x y z w)
)
Swapping q1 & q2 yields different results, quite neither like addition nor multiplication.
source

Bezier path see if it crosses

I have a code that lets the user draw a shape, I'm using UIBezierPath for this. But I need to see if the shape crosses itself, for example like this: http://upload.wikimedia.org/wikipedia/commons/0/0f/Complex_polygon.svg
Then it's not a a valid shape.
How can I find this?
Edit:
I still haven't solved this. I save all the points between the lines in the path in a array. And then I loop through the array and try to find if any lines intersects. But it does not work, sometimes it says that there is an intersection when it isn't.
I think that the problem is somewhere in this method.
-(BOOL)pathIntersects:(double *)x:(double *)y {
int count = pathPoints.count;
CGPoint p1, p2, p3, p4;
for (int a=0; a<count; a++) {
//Line 1
if (a+1<count) {
p1 = [[pathPoints objectAtIndex:a] CGPointValue];
p2 = [[pathPoints objectAtIndex:a+1] CGPointValue];
}else{
return NO;
}
for (int b=0; b<count; b++) {
//Line 2
if (b+1<count) {
p3 = [[pathPoints objectAtIndex:b] CGPointValue];
p4 = [[pathPoints objectAtIndex:b+1] CGPointValue];
}else{
return NO;
}
if (!CGPointEqualToPoint(p1, p3) && !CGPointEqualToPoint(p2, p3) && !CGPointEqualToPoint(p4, p1) && !CGPointEqualToPoint(p4, p2)
&& !CGPointEqualToPoint(p1, p2) && !CGPointEqualToPoint(p3, p4)) {
if (LineIntersect(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, x, y)) {
return YES;
}
}
}
}
return NO;
}
This is the code I found to see if two lines intersects, It's in C but I should work.
int LineIntersect(
double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4,
double *x, double *y)
{
double mua,mub;
double denom,numera,numerb;
denom = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1);
numera = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
numerb = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
/* Are the line coincident? */
if (ABS(numera) < 0.00001 && ABS(numerb) < 0.00001 && ABS(denom) < 0.00001) {
*x = (x1 + x2) / 2;
*y = (y1 + y2) / 2;
return(TRUE);
}
/* Are the line parallel */
if (ABS(denom) < 0.00001) {
*x = 0;
*y = 0;
return(FALSE);
}
/* Is the intersection along the the segments */
mua = numera / denom;
mub = numerb / denom;
if (mua < 0 || mua > 1 || mub < 0 || mub > 1) {
*x = 0;
*y = 0;
return(FALSE);
}
*x = x1 + mua * (x2 - x1);
*y = y1 + mua * (y2 - y1);
return(TRUE);
}
It depends on how complex the polygon drawn by the user can be and the number of points in the path. Ideally, there would be a point for all the vertices in the shape and nothing more. Get a CGPath from the UIBezierPath and use GCPathApply to hand the elements to a function, which adds each point to an array. Traverse the array with two for loops, one nested in the other, which checks each line segment against every line segment after it using a standard line-line intersection test. As soon as an intersection has been found, break from the loop. Or, if this were a convenience method, return a BOOL. That's the simplest way.
EDIT: Here's an example of a line-line intersection function which returns a BOOL telling you whether or not two segments cross. Pass in the two points that create the first segment followed by the two points that make the second segment. It was hastily modified from a piece of source code I found online quickly, but it works.
CGPoint lineSegmentsIntersect(CGPoint L1P1, CGPoint L1P2, CGPoint L2P1, CGPoint L2P2)
{
float x1 = L1P1.x, x2 = L1P2.x, x3 = L2P1.x, x4 = L2P2.x;
float y1 = L1P1.y, y2 = L1P2.y, y3 = L2P1.y, y4 = L2P2.y;
float bx = x2 - x1;
float by = y2 - y1;
float dx = x4 - x3;
float dy = y4 - y3;
float b_dot_d_perp = bx * dy - by * dx;
if(b_dot_d_perp == 0) {
return NO;
}
float cx = x3 - x1;
float cy = y3 - y1;
float t = (cx * dy - cy * dx) / b_dot_d_perp;
if(t < 0 || t > 1) {
return NO;
}
float u = (cx * by - cy * bx) / b_dot_d_perp;
if(u < 0 || u > 1) {
return NO;
}
return YES;
}
You can use it like this.
if (lineSegmentsIntersect(lineOnePointOne,lineOnePointTwo,lineTwoPointOne,lineTwoPointTwo)){
//segments intersect
} else {
//segments did not intersect
}
It's up to you to create the double loop to check the correct segments against one another.

how to zoom mandelbrot set

I have successfully implemented the mandelbrot set as described in the wikipedia article, but I do not know how to zoom into a specific section. This is the code I am using:
+(void)createSetWithWidth:(int)width Height:(int)height Thing:(void(^)(int, int, int, int))thing
{
for (int i = 0; i < height; ++i)
for (int j = 0; j < width; ++j)
{
double x0 = ((4.0f * (i - (height / 2))) / (height)) - 0.0f;
double y0 = ((4.0f * (j - (width / 2))) / (width)) + 0.0f;
double x = 0.0f;
double y = 0.0f;
int iteration = 0;
int max_iteration = 15;
while ((((x * x) + (y * y)) <= 4.0f) && (iteration < max_iteration))
{
double xtemp = ((x * x) - (y * y)) + x0;
y = ((2.0f * x) * y) + y0;
x = xtemp;
iteration += 1;
}
thing(j, i, iteration, max_iteration);
}
}
It was my understanding that x0 should be in the range -2.5 - 1 and y0 should be in the range -1 - 1, and that reducing that number would zoom, but that didnt really work at all. How can I zoom?
Suppose the center is the (cx, cy) and the length you want to display is (lx, ly), you can use the following scaling formula:
x0 = cx + (i/width - 0.5)*lx;
y0 = cy + (j/width - 0.5)*ly;
What it does is to first scale down the pixel to the unit interval (0 <= i/width < 1), then shift the center (-0.5 <= i/width-0.5 < 0.5), scale up to your desired dimension (-0.5*lx <= (i/width-0.5)*lx < 0.5*lx). Finally, shift it to the center you given.
first off, with a max_iteration of 15, you're not going to see much detail. mine has 1000 iterations per point as a baseline, and can go to about 8000 iterations before it really gets too slow to wait for.
this might help: http://jc.unternet.net/src/java/com/jcomeau/Mandelbrot.java
this too: http://www.wikihow.com/Plot-the-Mandelbrot-Set-By-Hand

Objective-C implementation of the Wilson Score Interval

I'm looking for an objective-c library or just the functions that can handle calculating the Wilson Score Interval explained here:
http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
For reference, here's a Ruby implementation from the same source:
require 'statistics2'
def ci_lower_bound(pos, n, power)
if n == 0
return 0
end
z = Statistics2.pnormaldist(1-power/2)
phat = 1.0*pos/n
(phat + z*z/(2*n) - z * Math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
end
Assuming the implementation for pnormaldist listed here is correct (i've copied it verbatim):
double pnormaldist(double qn)
{
double b[] = {1.570796288, 0.03706987906, -0.8364353589e-3, -0.2250947176e-3, 0.6841218299e-5, 0.5824238515e-5, -0.104527497e-5, 0.8360937017e-7, -0.3231081277e-8, 0.3657763036e-10, 0.6936233982e-12};
if(qn < 0.0 || 1.0 < qn)
return 0.0;
if(qn == 0.5)
return 0.0;
double w1 = qn;
if(qn > 0.5)
w1 = 1.0 - w1;
double w3 = -log(4.0 * w1 * (1.0 - w1));
w1 = b[0];
int i=1;
for(;i<11;i++)
w1 += b[i] * pow(w3,i);
if(qn > 0.5)
return sqrt(w1*w3);
return -sqrt(w1*w3);
}
double ci_lower_bound(int pos, int n, double power)
{
if(n==0)
return 0.0;
double z = pnormaldist(1-power/2);
double phat = 1.0*pos/n;
return (phat + z*z/(2*n) - z * sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n);
}