Finding point on a 3D line in C - c

I have two 3D points: (x1, y1, z1) and (x3, y3, z3) and want to find a point (x2, y2, z2) on that line given z2, which is between z1 and z3.
Here is what I have currently:
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
double *findPoint (double x1, double y1, double z1, double x3, double y3, double z3, double z2)
{
double *ret = malloc(3 * sizeof(double));
double dot = (x1 * x3) + (y1 * y3) + (z1 * z3);
printf("dot %e\n", dot);
double magprd = ((x1 * x1) + (y1 * y1) + (z1 * z1)) * ((x3 * x3) + (y3 * y3) + (z3 * z3));
printf("magprd %e\n", magprd);
double angle = acos(dot / magprd);
printf("angle %e\n", angle);
double distance = z2 / asin(angle);
printf("distance %e\n", distance);
double x2 = x1 - ((distance * x1) / 3);
double y2 = y1 - ((distance * y1) / 3);
ret[0] = x2;
ret[1] = y2;
ret[2] = z2;
return ret;
}
int main() {
// return pointer to array containing x2, y2, z2 corresponding to
// z=4 on line between point at x1, y1, z1 and x3, y3, z3
double *p = findPoint(1, 2, 3, 11, 12, 13, 4);
if(p) {
printf("point on line at z=4 is %e, %e, %e\n", p[0], p[1], p[2]);
free(p);
}
return 0;
}
This doesn't work properly, though:
$ clang -lm test.c -o test
$ ./test
dot 7.400000e+01
magprd 6.076000e+03
angle 1.558617e+00
distance nan
point on line at z=4 is nan, nan, 4.000000e+00
How can I fix findPoint so that it solves this problem? Thanks!

You math looks very complicated. I would suggest this code:
typedef struct { double x,y,z; } Point;
Point findPoint(Point a, Point b, double z) {
double dx = b.x - a.x;
double dy = b.y - a.y;
double dz = b.z - a.z;
if(dz == 0.0) {
// ERROR
return (Point){ 0,0,0 };
}
double p = (z - a.z) / dz;
return (Point){ a.x + p*dx, a.y + p*dy, a.z + p*dz };
}
If you do not want to use by value I suggest this:
int findPoint(const Point* a, const Point* b, double z, Point* c) {
double dx = b->x - a->x;
double dy = b->y - a->y;
double dz = b->z - a->z;
if(dz == 0.0) {
// ERROR
return 0;
}
double p = (z - a.z) / dz;
c->x = a.x + p*dx;
c->y = a.y + p*dy;
c->z = a.z + p*dz };
return 1;
}
Point* a = malloc(sizeof(Point));
a->x = 1;
a->y = 2;
a->z = 3;
Point* b = malloc(sizeof(Point));
b->x = 11;
b->y = 12;
b->z = 13;
Point* c = malloc(sizeof(Point));
if(findPoint(a,b,4,c)) {
printf("Result: %e %e %e\n", c->x, c->y, c->z);
}
else {
printf("Error!\n");
}

You can simplify your function to
double *findPoint (double x1, double y1, double z1, double x3, double y3, double z3, double z2)
{
double *ret = malloc(3 * sizeof(double));
double tmp = (z2 - z1)/(z3 - z1); // Assuming that z1 != z3
double x2 = x1 + tmp * (x3 - x1);
double y2 = y1 + tmp * (y3 - y1);
ret[0] = x2;
ret[1] = y2;
ret[2] = z2;
return ret;
}
That gives the result
point on line at z=4 is 2.000000e+00, 3.000000e+00, 4.000000e+00

Related

Converting projectile simulation to 3D causes drawing to disasppear?

I have a code that successfully draws projectiles in 2D, but I need to apply changes to make it in 3D.
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include <unistd.h>
#define g 9.8
#define PI 3.14
#define ESC 27
void initialize(void)
{
glClearColor(0, 0, 0, 0);
glColor3f(0.0, 1.0, 0.0);
glPointSize(3.0);
glEnable(GL_POINT_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 1000, 0, 500);
}
static void keyPressFunc(unsigned char key, int x, int y)
{
switch(key) {
case ESC:
exit(1);
}
}
void display(void)
{
float Pheta, Pheta2, Pheta3,Pheta4, Vo, time, time_top, d1, d2, d3, Uox1, Uox2, Uox3;
Vo = 60;
Pheta = 60;
Pheta2 = 30;
Pheta3 = 40;
Pheta4 = 50;
time = (2 * Vo * sin(Pheta * PI / 180)) / g;
time_top = time/2;
d1 = 500;
d2 = 650;
d3 = 800;
Uox1 = (d1 - Vo * cos(Pheta * PI / 180) * 2)/2;
Uox2 = (d2 - Vo * cos(Pheta * PI / 180)* time_top)/time_top;
Uox3 = (d3 - Vo * cos(Pheta * PI / 180) * 8)/8;
for(float t=0; t < 12 ; t += 0.0005)
{
float x1 = (Vo * cos(Pheta * PI / 180) * t);
float y1 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x2 = (d1 - Uox1 * t);
float y2 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x3 = (d2 - Uox2 * t);
float y3 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x4 = (d3 - Uox3 * t);
float y4 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
glBegin(GL_POINTS);
glVertex2d(x1, y1);
glVertex2d(x2, y2);
glVertex2d(x3, y3);
glVertex2d(x4, y4);
if (x1+0.1 >= x4 && x4+0.1 >= x1)
{
break;
}
glEnd();
glFlush();
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("C-Lang-Project");
glutKeyboardFunc(keyPressFunc);
initialize();
glutDisplayFunc(display);
glutMainLoop();
}
To make it 3D, I changed glVertex2d into glVertex3d, set a variable z and added it to the glVertex3d.
The final code that I've got:
#include <stdio.h>
#include <GL/glut.h>
#include <math.h>
#include <unistd.h>
#define g 9.8
#define PI 3.14
#define ESC 27
void initialize(void)
{
glClearColor(0, 0, 0, 0);
glColor3f(0.0, 1.0, 0.0);
glPointSize(3.0);
glEnable(GL_POINT_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 1000, 0, 500);
}
static void keyPressFunc(unsigned char key, int x, int y)
{
switch(key) {
case ESC:
exit(1);
}
}
void display(void)
{
float Pheta, Pheta2, Pheta3,Pheta4, Vo, time, time_top, d1, d2, d3, Uox1, Uox2, Uox3, z;
Vo = 60;
Pheta = 60;
Pheta2 = 30;
Pheta3 = 40;
Pheta4 = 50;
time = (2 * Vo * sin(Pheta * PI / 180)) / g;
time_top = time/2;
d1 = 500;
d2 = 650;
d3 = 800;
z = 15;
Uox1 = (d1 - Vo * cos(Pheta * PI / 180) * 2)/2;
Uox2 = (d2 - Vo * cos(Pheta * PI / 180)* time_top)/time_top;
Uox3 = (d3 - Vo * cos(Pheta * PI / 180) * 8)/8;
for(float t=0; t < 12 ; t += 0.0005)
{
float x1 = (Vo * cos(Pheta * PI / 180) * t);
float y1 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x2 = (d1 - Uox1 * t);
float y2 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x3 = (d2 - Uox2 * t);
float y3 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x4 = (d3 - Uox3 * t);
float y4 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
glBegin(GL_POINTS);
glVertex3d(x1, y1, z);
glVertex3d(x2, y2, z);
glVertex3d(x3, y3, z);
glVertex3d(x4, y4, z);
if (x1+0.1 >= x4 && x4+0.1 >= x1)
{
break;
}
glEnd();
glFlush();
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("C-Lang-Project");
glutKeyboardFunc(keyPressFunc);
initialize();
glutDisplayFunc(display);
glutMainLoop();
}
But it does not show any mistake, just shows a black window.
P.S. I am using OpenGL & freeglut
The scene is clipped by by the near plane of the orthographic projection.
The z coordiante of the geoemtry is set z=15; but the orthographic projection is set gluOrtho2D(0, 1000, 0, 500);. gluOrtho2D sets a near plane of -1 and a far plane of 1.
The view space z coordinate has to be between the near and far plane.
Since the view space z axis points out of the viewport, the view space z coordinate is -15.
This means, if z=15 then the following condition has to be fulfilled:
near < -15 < far
Change the orthographic projection to solve the issue. Use glOrtho:
e.g.
void initialize(void)
{
// [...]
glOrtho(0, 1000, 0, 500, -20, 1);
}
Of course it is possible to switch to perspective projection. In this case you've to invert the and z coordinate.
To get all the geometry on the screen (in clip space), I recommend to increase the amount to of the z coordinate and (of course) the distance to the far plane:
e.g.
void display(void)
{
float z = -500;
// [...]
}
void initialize(void)
{
// [...]
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 90.0, 1000.0 / 500.0, 0.1, 1000.0 );
}
Don't implement a render loop in the event processing loop. Use glutPostRedisplay to force the display to be repainted:
float t=0;
void display(void)
{
float Pheta, Pheta2, Pheta3,Pheta4, Vo, time, time_top, d1, d2, d3, Uox1, Uox2, Uox3, z;
Vo = 60; Pheta = 60; Pheta2 = 30; Pheta3 = 40; Pheta4 = 50;
time = (2 * Vo * sin(Pheta * PI / 180)) / g;
time_top = time/2; d1 = 500; d2 = 650; d3 = 800;
z = 15;
Uox1 = (d1 - Vo * cos(Pheta * PI / 180) * 2)/2;
Uox2 = (d2 - Vo * cos(Pheta * PI / 180)* time_top)/time_top;
Uox3 = (d3 - Vo * cos(Pheta * PI / 180) * 8)/8;
float x1 = (Vo * cos(Pheta * PI / 180) * t);
float y1 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x2 = (d1 - Uox1 * t);
float y2 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x3 = (d2 - Uox2 * t);
float y3 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
float x4 = (d3 - Uox3 * t);
float y4 = (Vo * sin(Pheta * PI / 180) * t - 0.5 * g * t * t);
glBegin(GL_POINTS);
glVertex3d(x1, y1, z);
glVertex3d(x2, y2, z);
glVertex3d(x3, y3, z);
glVertex3d(x4, y4, z);
glEnd();
t += 0.0005;
glFlush();
glutPostRedisplay();
}

Mandelbrot Set not displayed

a Mandelbrot set fractal using C programming and OpenGL. Here is my code. It is only displaying a dot in the center right now. I cannot figure out where I am going wrong. I'm pretty sure my math is correct. Maybe I have something in the wrong loop?
This picture is what Im trying to get
Here is my code so far:
#include <GLUT/glut.h>
#include <math.h>
void init(void);
void display(void);
const int screenWidth = 640;
const int screenHeight = 480;
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow("Mandelbrot");
// glViewport(-320, -320, 320, 320);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void init(void) {
glMatrixMode(GL_PROJECTION);
gluOrtho2D(-500.0, screenWidth, -500.0, screenHeight);
// A = screenWidth / 4.0;
// B = 0.0;
// C = D = screenHeight / 2.0;
}
void display(void) {
GLdouble x, f, y, xtemp, y0, x0, iteration, maxInteration;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glColor3f(0.0, 0.0, 0.0);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (y0 = - 1; y0 < 1.1; y0 = y0 + 0.0025) {
for (x0 = -2.5; x0 < 1.1; x0 = x0 + 0.0025) {
x = 0;
y = 0;
iteration = 0;
maxInteration = 1000;
while (((x * x) + (y * y) < (2 * 2)) && iteration < maxInteration) {
xtemp = (x * x) - (y * y) + x0;
y = (2 * x * y) + y0;
x = xtemp;
iteration = iteration + 1;
if (y <= 2) {
glBegin(GL_POINTS);
glVertex2d(x / 750, y / 750);
glEnd();
}
}
}
}
glFlush();
}
Here is my updated code after fixing suggestions in comments.. It results in the above image.. However, now I am trying to create the grey circles around the object??? Im attempting to do this through the else at the end... any thoughts?
#include <GLUT/glut.h>
#include <math.h>
void init(void);
void display(void);
const int screenWidth = 640;
const int screenHeight = 640;
GLdouble A, B, C, D;
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(screenWidth, screenHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow("Mandelbrot");
glViewport(-1, 1, -1, 1);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}
void init(void) {
//glMatrixMode(GL_PROJECTION);
gluOrtho2D(-3.0, 3.0, -3.0, 3.0);
A = screenWidth / 4.0;
B = 0.0;
C = D = screenHeight / 2.0;
}
void display(void)
{
GLdouble x, f, y, xtemp, y0, x0, iteration, maxInteration;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glEnable(GL_POINT_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for(y0 = -1; y0< 1.1; y0 = y0 + 0.0025){
for (x0 = -2.5; x0 < 1.1; x0 = x0 + 0.0025) {
x = 0;
y = 0;
iteration = 0;
maxInteration = 200;
while(((x*x) + (y*y) <(2*2)) && iteration <maxInteration){
xtemp = (x*x) - (y*y) + x0;
y = (2*x*y) +y0;
x = xtemp;
iteration = iteration + 1;
}
if(iteration >= maxInteration){
glBegin(GL_POINTS);
glVertex2d(x0 , y0);
glColor3f(0.0, 0.0, 0.0);
glEnd();
}
else{
????
}
}
}
glFlush();
}
First of all, here's some advices regarding to your code:
When working with complex numbers or vectors i'd recommend you to use a proper fast math library so you can avoid operating with individual components, there are very fast cpu math libraries out there which can use SIMD instructions and your code will become more readable
The way your drawing the mandelbrot is really a bad idea. I mean, yeah, it's alright if you just want to dump simple images and learning the basics but that's pretty much. Don't use GL_POINTS and try to render/update textures directly, or even better, use fragment shaders + glsl (recommended way) so your mandelbrot will be rendered very fast even if you're using non-optimized maths.
Coordinate systems, if you still insist on using GL_POINTS the way you're doing, i'd just use directly the window coordinates and going from that space to the mandelbrot math domain ie: [0,0,w,h]<->[-1,-1,1,1]
Here's a little example of what i mean:
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
const int screen_width = 640;
const int screen_height = 480;
float c[4];
float z[4];
float clamp(float x, float vmin, float vmax) {
if (x < vmin) {
return vmin;
} else if (x > vmax) {
return vmax;
}
return x;
}
void dc_add(float *a, float *b, float *res) {
res[0] = a[0] + b[0];
res[1] = a[1] + b[1];
res[2] = a[2] + b[2];
res[3] = a[3] + b[3];
}
void dc_mul(float *a, float *b, float *res) {
res[0] = a[0] * b[0] - a[1] * b[1];
res[1] = a[0] * b[1] + a[1] * b[0];
res[2] = a[0] * b[2] + a[2] * b[0] - a[1] * b[3] - a[3] * b[1];
res[3] = a[0] * b[3] + a[3] * b[0] + a[2] * b[1] + a[1] * b[2];
}
void dc_sqr(float *a, float *res) {
res[0] = a[0] * a[0] - a[1] * a[1];
res[1] = 2.0f * a[0] * a[1];
res[2] = 2.0f * (a[0] * a[2] - a[1] * a[3]);
res[3] = 2.0f * (a[0] * a[3] + a[1] * a[2]);
}
float dot(float x, float y) { return x * x + y * y; }
void init(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, screen_width, 0, screen_height);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
for (int y = 0; y < screen_height; y++) {
for (int x = 0; x < screen_width; x++) {
float px = -1.0f + 2.0f * (float)x / (float)screen_width;
float py = -1.0f + 2.0f * (float)y / (float)screen_height;
px *= (float)screen_width / (float)screen_height;
float tz = 0.5f;
float zo = powf(1.2f, 1.2f);
float m2 = 0.0f;
float co = 0.0f;
float temp[4];
c[0] = px * zo; c[1] = py * zo; c[2] = 1.0; c[3] = 0.0;
z[0] = 0.0f; z[1] = 0.0f; z[2] = 0.0f; z[3] = 0.0f;
for (int i = 0; i < 256; i++) {
if (m2 > 1024.0f) continue;
dc_sqr(z, temp);
dc_add(temp, c, z);
m2 = dot(z[0], z[1]);
co += 1.0f;
}
float d = 0.0f;
if (co < 256.0f) {
d = sqrtf((dot(z[0], z[1]) / dot(z[2], z[3]))) *
logf(dot(z[0], z[1]));
}
d = clamp(4.0f * d / zo, 0.0f, 1.0f);
d = powf(d, 0.25f);
glColor3f(d, d, d);
glBegin(GL_POINTS);
glVertex2d(x, y);
glEnd();
}
}
glFlush();
glutSwapBuffers();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(screen_width, screen_height);
glutInitWindowPosition(0, 0);
glutCreateWindow("Mandelbrot");
init();
glutDisplayFunc(display);
glutIdleFunc(display);
glutMainLoop();
return 0;
}
And here's the output:
Maths of the above example are based on this shadertoy.
The above code is terrible unefficient and slow but it serves the main purpose to prove you the way you shouldn't ever code a proper mandelbrot.
Happy coding.
There is a simple problem in you code: you use a division instead of a multiplication to compute the pixel coordinates: change glVertex2d(x / 750, y / 750); to
glVertex2d(x * 750, y * 750);
However, this is not the correct method to compute the Mandelbrot set. You should instead compute the number of iterations for the squared module to exceed 4.0, and then set the color of the pixel at (x0 * 300, y0 * 300) to that number as a palette entry or a gray level.

In Visual Studio , Why does the C Program running in Debug mode ,is not running in Runtime

I am new to Visual Studio tool.The program is compiled successfully and the method Multiplication is called succesfully in debugging mode,whereas it is not getting executed in run time .
Here is my code
#include<stdio.h>
#include<math.h>
int Splitting(int *, int);
int Multiplication1(int, int, int, int);
int main()
{
int x1 = 1234567891, y1 = 567891, x = x1, y = y1, a1, b1, c1, d1, count = 0, Answer = 0;
while (x1 % 10 != 0)
{
x1 = x1 / 10;//1
count++;//3
}
x1 = x;
printf("count=%d", count);
a1 = Splitting(&x, count);
b1 = x;
printf("a1=%d,b1=%d\n", a1, b1);
// printf("a1=%d,b1=%d\n", a1,b1);
count = 0;
while (y1 % 10 != 0)
{
y1 = y1 / 10;
count++;
}
y1 = y;
c1 = Splitting(&y, count);
d1 = y;
printf("a1=%d,b1=%d,c1=%d,d1=%d\n", a1, b1, c1, d1);
Answer = Multiplication1(a1, b1, c1, d1);
printf("Answer=%d\n", Answer);
return 0;
}
int Splitting(int *x, int count)
{
int x1 = *x, x2, a = 0, b = 0, a1 = 0, b1 = 0;
for (int i = 0;i < count / 2;i++)//0,1
{
a = x1 % 10;//4,3
x2 = x1 / pow(10, count / 2);//12345
b = x2 % 10;//6
x1 = x1 / 10;//123,
x2 = x2 / 10;
a1 += a * pow(10, i);//4+30=34,
b1 += b* pow(10, i);//=>12*
}
printf("Splitting,a1=%d,b1=%d\n", a1, b1);
*x = a1;
return b1;
}
int Multiplication1(int a, int b, int c, int d)
{
printf("Inside Multiplication function");
printf("a=%d,b=%d,c=%d,d=%d", a, b, c, d);
unsigned long step1, step2, step3, step4, Answer;
Answer = a+b+c+d;
printf("Answer=%d\n", Answer);
return 0;
}

Normalize a Vector from a struct in C

typedef struct
{
float x, y, z;
} VECTOR;
Write a function that takes a pointer to a VECTOR structure and normalizes the x, y, and z components
I realize you can normalize the Vector by getting the length and dividing x, y, and z by the length. but how would I do this with the code presented here.
Here is my attempt at this.
Void Norm(*VECTOR)
{
x = x / *VECTOR.Length;
y = y / *VECTOR.Length;
z = z / *VECTOR.Length;
}
#include <math.h>
typedef struct
{
float x, y, z;
} VECTOR;
void normalize( VECTOR* p )
{
float w = sqrt( p->x * p->x + p->y * p->y + p->z * p->z );
p->x /= w;
p->y /= w;
p->z /= w;
}

Golden Section Routine Segmentation Fault

I'm trying to find minimum point of Gamma function by Golden Section method. But when I execute the program I get segmentation fault error. I think since I'm a newbie C user, the problem may be due to calling the function Min_Search_Golden_Section wrong. Here is my complete code. I can't find my mistake. Thanks in advance.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define A 12
#define sqrt5 2.236067977499789696
static int Stopping_Rule(double x0, double x1, double tolerance);
double sp_gamma(double z)
{
const int a = A;
static double c_space[A];
static double *c = NULL;
int k;
double accm;
if ( c == NULL ) {
double k1_factrl = 1.0; /* (k - 1)!*(-1)^k with 0!==1*/
c = c_space;
c[0] = sqrt(2.0*M_PI);
for(k=1; k < a; k++) {
c[k] = exp(a-k) * pow(a-k, k-0.5) / k1_factrl;
k1_factrl *= -k;
}
}
accm = c[0];
for(k=1; k < a; k++) {
accm += c[k] / ( z + k );
}
accm *= exp(-(z+a)) * pow(z+a, z+0.5); /* Gamma(z+1) */
return accm/z;
}
void Min_Search_Golden_Section( double (*f)(double), double* a, double *fa,
double* b, double* fb, double tolerance)
{
static const double lambda = 0.5 * (sqrt5 - 1.0);
static const double mu = 0.5 * (3.0 - sqrt5); // = 1 - lambda
double x1;
double x2;
double fx1;
double fx2;
// Find first two internal points and evaluate
// the function at the two internal points.
x1 = *b - lambda * (*b - *a);
x2 = *a + lambda * (*b - *a);
fx1 = f(x1);
fx2 = f(x2);
// Verify that the tolerance is an acceptable number
if (tolerance <= 0.0) tolerance = sqrt(DBL_EPSILON) * (*b - *a);
// Loop by exluding segments from current endpoints a, b
// to current internal points x1, x2 and then calculating
// a new internal point until the length of the interval
// is less than or equal to the tolerance.
while ( ! Stopping_Rule( *a, *b, tolerance) ) {
if (fx1 > fx2) {
*a = x1;
*fa = fx1;
if ( Stopping_Rule( *a, *b, tolerance) ) break;
x1 = x2;
fx1 = fx2;
x2 = *b - mu * (*b - *a);
fx2 = f(x2);
} else {
*b = x2;
*fb = fx2;
if ( Stopping_Rule( *a, *b, tolerance) ) break;
x2 = x1;
fx2 = fx1;
x1 = *a + mu * (*b - *a);
fx1 = f(x1);
}
}
return;
}
int main()
{
double x;
double a = 0.0, b = 4.0, fa = 0.00001, fb = 6.0;
double fx = sp_gamma(x);
Min_Search_Golden_Section( &fx, &a, &fa, &b, &fb, 0.0000001);
return 0;
}
static int Stopping_Rule(double x0, double x1, double tolerance)
{
double xm = 0.5 * fabs( x1 + x0 );
if ( xm <= 1.0 ) return ( fabs( x1 - x0 ) < tolerance ) ? 1 : 0;
return ( fabs( x1 - x0 ) < tolerance * xm ) ? 1 : 0;
}
You should be getting a compiler error. The first argument to Min_Search_Golden_Section should be a function pointer, but you pass the address of a variable instead.
When you get compiler errors, fix them - don't run the program and hope. :)
I guess you just meant to write:
Min_Search_Golden_Section( &sp_gamma, &a, &fa, &b, &fb, 0.0000001);

Resources