I am trying to make a method to calculate a ray box intersection in C. Most of the procedures I googled show methods that return bools (if there is or there isn't an intersection). However, I need a method that can return a tuple (I know there are no tuples in C, but I made a struct to represent it). Specifically, I need the values of tmin and tmax, even though they are negative, and assigning them a negative value if the value does not exist. How should I manage the returns of this to work properly? The code I produced in C is based on the code displayed in this page: https://tavianator.com/fast-branchless-raybounding-box-intersections-part-2-nans/. The actual implementation of the code in my program is as follows:
RectMinMax* Intersection(BoundingBox* b, Ray* r) {
RectMinMax* TMinMax = malloc(sizeof(RectMinMax));
float tmin = -INFINITY, tmax = INFINITY;
if (ray_get_direction(r).X != 0) {
float t1 = (b->x - ray_get_origin(r).X) / ray_get_direction(r).X;
float t2 = ((b->x + b->length) - ray_get_origin(r).X)/ ray_get_direction(r).X;
tmin = fmaxf(tmin, fminf(t1, t2));
tmax = fminf(tmax, fmaxf(t1, t2));
}
else if (ray_get_origin(r).X <= b->x || ray_get_origin(r).X >= (b->x + b->length)) {
TMinMax->min = -55;
TMinMax->max = -55;
return TMinMax;
}
if (ray_get_direction(r).Y != 0) {
float t1 = (b->y - ray_get_origin(r).Y) / ray_get_direction(r).Y;
float t2 = ((b->y + b->width) - ray_get_origin(r).Y)/ ray_get_direction(r).Y;
tmin = fmaxf(tmin, fminf(t1, t2));
tmax = fminf(tmax, fmaxf(t1, t2));
}
else if (ray_get_origin(r).Y <= b->y || ray_get_origin(r).Y >= (b->y + b->width)) {
TMinMax->min = -55;
TMinMax->max = -55;
return TMinMax;
}
if (ray_get_direction(r).Z != 0) {
float t1 = (b->z - ray_get_origin(r).Z) / ray_get_direction(r).Z;
float t2 = ((b->z + b->height) - ray_get_origin(r).Z)/ ray_get_direction(r).Z;
tmin = fmaxf(tmin, fminf(t1, t2));
tmax = fminf(tmax, fmaxf(t1, t2));
}
else if (ray_get_origin(r).Z <= b->z || ray_get_origin(r).Z >= (b->z + b->height)) {
TMinMax->min = -55;
TMinMax->max = -55;
return TMinMax;
}
if (tmax > tmin && tmax > 0) {
TMinMax->min = tmin;
TMinMax->max = tmax;
return TMinMax;
}
else {
TMinMax->min = -55;
TMinMax->max = -55;
return TMinMax;
}
}
RectMinMax is just a struct with to attributes max and min. In the code I used -55 to represent the "return false" cases of the code in the link. I understand I am leaving out cases in which tmax is positive and tmin negative, for example, but I do not know how to fix it.
Related
I'm trying to write a convolution function in C for my computer vision study.
In this function, every pixel in the convolved image is a sum of product of original image and filter kernel like in this image and this gif.
In the code below pixel values are float. get_pixel() function gets the pixel value at given indexes. set_pixel() function sets the value to given indexes.
image convolve(image im, image filter) {
// imx, imy, imc: indexes of image pixels
// fix, fiy: indexes of filter pixels
// rx, ry: relative indexes of pixels
image convolved_img = make_image(im.w, im.h, im.c); // image with same dimensions
float value = 0; // pixel value
int oxo = floor(filter.w / 2); // half of the kernel width
int xox = floor(filter.h / 2); // half of the kernel height
// Convolution Loop
for(int imc = 0; imc < im.c; imc++) { // for every channel
for(int imx = 0; imx < im.w; imx++) {
for(int imy = 0; imy < im.h; imy++) { // for every pixel
value = 0;
for(int fix = 0; fix < filter.w; fix++) {
for(int fiy = 0; fiy < filter.h; fiy++) {
int rx = imx - oxo + fix;
int ry = imy - xox + fiy;
value += get_pixel(filter, fix, fiy, 0) * get_pixel(im, rx, ry, imc);
}
}
set_pixel(convolved_img, imx, imy, imc, value);
}
}
}
return convolved_img;
}
I'm getting segmentation fault (core dumped) error. After debugging I realized its because of line:
value += get_pixel(filter, fix, fiy, 0) * get_pixel(im, rx, ry, imc);
When I gave fixed values of rx and ry, the program executes successfully. Inside the loop I printed the values of imx, imy, fix, fiy, rx, ry and everything works until a portion of the image has processed; after uncertain time of loop then program crushes without any reason.
I'm sure that it cannot be a index bounds related because I truncated indexes inside get_pixel() function below which I get stored value from a long array of floats.
float get_pixel(image im, int x, int y, int c) {
if(x > im.w) {x = im.w;}
else if(y > im.h) {y = im.h;}
else if(c > im.c) {c = im.c;}
else if(x < 0) {x = 0;}
else if(y < 0) {y = 0;}
else if(c < 0) {c = 0;}
int index = (c * (im.h * im.w)) + (y * im.w) + x;
return im.data[index];
}
Here is my thought about this operation as pseudo-code:
create convolved_image with same dimensions
for every pixel (imx, imy) in image {
float value = 0;
for every pixel (fix, fiy) in filter {
// calculate relative pixel coordinates
int rx = imx - (filter / 2) + fix;
int ry = imy - (filter / 2) + fiy;
value += filter(fix, fiy) * image(rx, ry);
}
set pixel of convolved_image to value
}
Am I missing something? What is the fault in my approach? Or is there a better way for this operation?
This is clearly an out of bounds access:
for(int fix = 0; fix < filter.w; fix++) {
for(int fiy = 0; fiy < filter.h; fiy++) {
int rx = imx - oxo + fix;
int ry = imy - xox + fiy;
value += get_pixel(filter, fix, fiy, 0) * get_pixel(im, rx, ry, imc);
}
}
With imx going up to im.x and fix going up to 2*oxo you are clearly larger than im.x. Same for imy.
You try to limit the range but that is not correct:
float get_pixel(image im, int x, int y, int c) {
if(x > im.w) {x = im.w;}
else if(y > im.h) {y = im.h;}
else if(c > im.c) {c = im.c;}
else if(x < 0) {x = 0;}
else if(y < 0) {y = 0;}
else if(c < 0) {c = 0;}
int index = (c * (im.h * im.w)) + (y * im.w) + x;
return im.data[index];
}
You forgot that all parameters can be wrong. You stop after first.
Also you limit to size+1 which also is wrong.
Change like this:
float get_pixel(image im, int x, int y, int c) {
if(x >= im.w) {x = im.w-1;}
else if(x < 0) {x = 0;}
if(y >= im.h) {y = im.h-1;}
else if(y < 0) {y = 0;}
if(c >= im.c) {c = im.c-1;}
else if(c < 0) {c = 0;}
int index = (c * (im.h * im.w)) + (y * im.w) + x;
return im.data[index];
}
I am writing maze generator and at the some point I have to choose random unvisited neighbour of a cell. The first idea was just to enumerate neighbours such as left = 0, top = 1, right = 2, bottom = 3 and use rand() % 4 to generate random number and choose appropriate cell. However, not all cells features 4 neighbours, so that I had to write following code:
Cell* getRandomNeighbour(const Maze* const maze, const Cell* const currentCell) {
int randomNumb = rand() % 4;
int timer = 1;
while(timer > 0) {
if (randomNumb == 0 && currentCell->x < maze->width-1 && maze->map[currentCell->y][currentCell->x+1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x+1];
if (randomNumb == 1 && currentCell->x > 0 && maze->map[currentCell->y][currentCell->x-1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x-1];
if (randomNumb == 2 && currentCell->y < maze->height-1 && maze->map[currentCell->y+1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y+1][currentCell->x];
if (randomNumb == 3 && currentCell->y > 0 && maze->map[currentCell->y-1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y-1][currentCell->x];
timer--;
randomNumb = rand() % 4;
}
if (currentCell->x < maze->width-1 && maze->map[currentCell->y][currentCell->x+1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x+1];
if (currentCell->x > 0 && maze->map[currentCell->y][currentCell->x-1].isUnvisited)
return &maze->map[currentCell->y][currentCell->x-1];
if (currentCell->y < maze->height-1 && maze->map[currentCell->y+1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y+1][currentCell->x];
if (currentCell->y > 0 && maze->map[currentCell->y-1][currentCell->x].isUnvisited)
return &maze->map[currentCell->y-1][currentCell->x];
return NULL;
}
So, if after 10 iterations the right decision isn't chosen, it will be picked by brute force. This approach seems to be good for the reason that varying of variable timer changes the complexity of maze: the less timer is, the more straightforward maze is. Nevertheless, if my only purpose is to generate completely random maze, it takes a lot of execution time and look a little bit ugly. Is there any pattern(in C language) or way of refactoring that could enable me to deal with this situation without long switches and a lot of if-else constructions?
As #pat and #Ivan Gritsenko suggested, you can limit your random choice to the valid cells only, like this:
Cell* getRandomNeighbour(const Maze* const maze, const Cell* const currentCell)
{
Cell *neighbours[4] = {NULL};
int count = 0;
// first select the valid neighbours
if ( currentCell->x < maze->width - 1
&& maze->map[currentCell->y][currentCell->x + 1].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y][currentCell->x + 1];
}
if ( currentCell->x > 0
&& maze->map[currentCell->y][currentCell->x - 1].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y][currentCell->x - 1];
}
if ( currentCell->y < maze->height - 1
&& maze->map[currentCell->y + 1][currentCell->x].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y + 1][currentCell->x];
}
if ( currentCell->y > 0
&& maze->map[currentCell->y - 1][currentCell->x].isUnvisited ) {
neighbours[count++] = &maze->map[currentCell->y - 1][currentCell->x];
}
// then choose one of them (if any)
int chosen = 0;
if ( count > 1 )
{
int divisor = RAND_MAX / count;
do {
chosen = rand() / divisor;
} while (chosen >= count);
}
return neighbours[chosen];
}
The rationale behind the random number generation part (as opposed to the more common rand() % count) is well explained in this answer.
Factoring repeated code, and a more disciplined way of picking the order of directions to try yields this:
// in_maze returns whether x, y is a valid maze coodinate.
int in_maze(const Maze* const maze, int x, int y) {
return 0 <= x && x < maze->width && 0 <= y && y < maze->height;
}
Cell *get_random_neighbour(const Maze* const maze, const Cell* const c) {
int dirs[] = {0, 1, 2, 3};
// Randomly shuffle dirs.
for (int i = 0; i < 4; i++) {
int r = i + rand() % (4 - i);
int t = dirs[i];
dirs[i] = dirs[r];
dirs[r] = t;
}
// Iterate through the shuffled dirs, returning the first one that's valid.
for (int trial=0; trial<4; trial++) {
int dx = (dirs[trial] == 0) - (dirs[trial] == 2);
int dy = (dirs[trial] == 1) - (dirs[trial] == 3);
if (in_maze(maze, c->x + dx, c->y + dy)) {
const Cell * const ret = &maze->map[c->y + dy][c->x + dx];
if (ret->isUnvisited) return ret;
}
}
return NULL;
}
(Disclaimer: untested -- it probably has a few minor issues, for example const correctness).
I'm trying to convert a fraction to floating point and use it for comparison.
but the values are too small and it returns true for the results of the Boolean variables. is my converision correct ? or should I do it in another way which I don't know ?
A test case:
// result is -0.0074
float coilh0re = fr32_to_float(GO_coil_H[0].re)*0.8f;
// result is -0.0092
float coilrefundamental = fr32_to_float(CoilEepromData.coilboardhspule.reFundamental);
// result is -0.01123
float coilh0re2 = fr32_to_float(GO_coil_H[0].re)*1.2f;
-0.0074>-0.0092> -0.01123
here is a snipped of the code
bool resultA = fr32_to_float(GO_coil_H[0].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reFundamental) ? 1 : 0;
bool resultB = fr32_to_float(CoilEepromData.coilboardhspule.reFundamental) <= fr32_to_float(GO_coil_H[0].re)*1.2f ? 1 : 0;
bool resultAB = !(resultA & resultB); // always true
bool resultC = fr32_to_float(GO_coil_H[1].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic) ? 1:0;
bool resultD = fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic) <= fr32_to_float(GO_coil_H[1].re)*1.2f ? 1:0;
bool resultCD = !(resultC & resultD); // always true
bool resultE = fr32_to_float(GO_coil_H[0].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imFundamental)? 1 : 0;
bool resultF = fr32_to_float(CoilEepromData.coilboardhspule.imFundamental) <= fr32_to_float(GO_coil_H[0].im)*1.2f ? 1 : 0;
bool resultEF = !(resultE & resultF);// always true
bool resultG = fr32_to_float(GO_coil_H[1].im)*0.8f < CoilEepromData.coilboardhspule.imHarmonic ? 1 : 0;
bool resultH = fr32_to_float(CoilEepromData.coilboardhspule.imHarmonic) <= fr32_to_float(GO_coil_H[1].im)*1.2f ? 1 : 0;
bool resultGH = !(resultG & resultH);// always true
if(! ((fr32_to_float(GO_coil_H[0].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reFundamental)) && (fr32_to_float(CoilEepromData.coilboardhspule.reFundamental) <= fr32_to_float(GO_coil_H[0].re)*1.2f) )
|| ! ((fr32_to_float(GO_coil_H[1].re)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic)) && (fr32_to_float(CoilEepromData.coilboardhspule.reHarmonic) <= fr32_to_float(GO_coil_H[1].re)*1.2f) )
|| ! ((fr32_to_float(GO_coil_H[0].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imFundamental)) && (fr32_to_float(CoilEepromData.coilboardhspule.imFundamental) <= fr32_to_float(GO_coil_H[0].im)*1.2f) )
|| ! ((fr32_to_float(GO_coil_H[1].im)*0.8f < fr32_to_float(CoilEepromData.coilboardhspule.imHarmonic)) && (fr32_to_float(CoilEepromData.coilboardhspule.imHarmonic) <= fr32_to_float(GO_coil_H[1].im)*1.2f) ) )
{
eUserCode = E_USER_SOIL_FAILED;
eProcessState = E_ERROR_HANDLING;
}
}
If appears OP wants to test if a value reFundamental is in range +/-20% of re. This is not a float precision issue, but a math one.
// Simplified problem
float re = -0.01123f/1.2f;
float reFundamental = -0.0092f;
bool resultA = re*0.8f < reFundamental;
bool resultB = reFundamental <= re*1.2f;
bool resultAB = !(resultA & resultB); // always true
But the values are negative and so the < and <= should be reversed.
Various alternatives. Example: (Adjust to taste)
bool in_range(float x, float limit, float factor) {
float limitp = limit*(1.0f + factor);
float limitm = limit*(1.0f - factor);
if (x > limitm) return x <= limitp;
if (x < limitm) return x >= limitp;
return x == limitp;
}
bool resultAB = !in_range(fr32_to_float(CoilEepromData.coilboardhspule.reFundamental),
fr32_to_float(GO_coil_H[0].re), 0.20);
If you want to compare fractions - do not use floating-point at all. Convert them to the same denominator and compare numerators.
Given an axis-aligned cubemap centered in the origin and an arbitrary point in 3D space, the straightforward way to check which face the point lies into consists in grabbing the coordinate with the greatest magnitude and selecting the face corresponding to that component.
The naive code would read as follows:
if (fabs(point.x) >= fabs(point.y) && fabs(point.x) >= fabs(point.z)) {
if (point.x >= 0) {face=0;} else {face=1;}
}
if (fabs(point.y) >= fabs(point.x) && fabs(point.y) >= fabs(point.z)) {
if (point.y >= 0) {face=2;} else {face=3;}
}
if (fabs(point.z) >= fabs(point.x) && fabs(point.z) >= fabs(point.y)) {
if (point.z >= 0) {face=4;} else {face=5;}
}
Is there a way to achieve the same thing that is considered to be better in C? Would branchless code be more optimal?
Any inline assembly standard of choice can alternatively be used for the purpose.If necessary, all the \>= operators can be turned into \> operators.
Might not look like much, but the first three if statements eliminate all of the calls to fabs as well as replacing the inner if statements in the posted code. The final if/else takes a maximum of two compares/branches to determine the answer.
if ( point.x < 0 ) {
x = -point.x;
fx = 1;
} else {
x = point.x;
fx = 0;
}
if ( point.y < 0 ) {
y = -point.y;
fy = 3;
} else {
y = point.y;
fy = 2;
}
if ( point.z < 0 ) {
z = -point.z;
fz = 5;
} else {
z = point.z;
fz = 4;
}
if ( x >= y ) {
if ( x >= z ) { face = fx; } else { face = fz; }
} else {
if ( y >= z ) { face = fy; } else { face = fz; }
}
My question is write an efficient algorithm to check whether a given number n is of the form ab where a, b are integers >= 2. I have tried the following but it is not time efficient.
int cnt = 0;
long long i, sq = sqrt(n);
for (i = 2; i <= sq; i++) {
if (n % i == 0) {
cnt++;
n = n / i;
while (n % i == 0) {
n /= i;
cnt++;
}
if (n == 1) {
break;
}
}
}
if (cnt >= 2) {
return true;
}
return false;
I'm assuming you meant pow(a, b) not a^b, since ^ in C/C++ is the XOR operator.
Your problem is known as detecting perfect powers and there is a lot of literature you can find in the internet.
For example: Detecting perfect powers in linear time by Daniel Bernstein.
You can both fix your code and speed it up considerably by replacing:
if (n == 1) break;
with
return (n == 1);
Then since you went to the trouble of computing sqrt(n), might as well have an early exit for perfect squares:
if (n == sq * sq) return true;
Idea:
if n = 3^5 then:
ln(n) / ln(3) = 5
exp( ln(n) / 5 ) = 3
Sample JavaScript code, open inspector/console for results (easily convertible to C):
http://jsfiddle.net/8wuUK/
function powerSplit( n ){
console.log('n =', n);
var log = Math.log, exp = Math.exp, abs = Math.abs,
floor = Math.floor, round = Math.round;
var epsilon = 0.001;
var logn = log( n );
var pow = floor( log(n) / log(2) ) + 1;
do{
pow --;
var base = exp( logn / pow );
var intbase = round( base );
if( abs( base - intbase ) > epsilon ) continue;
//console.log( base, intbase, pow, isExactPower( n, intbase ) );
if( isExactPower( n, intbase )) return 'n = ' + intbase +' ^ ' + pow;
}while( pow >= 1 );
return 'n is not a power';
}
function isExactPower( n, base ){
while( n > 1 ){
if( n % base ) return false;
n /= base;
};
return true;
};