Why the array seem leaks after I should malloc enough space? - arrays

I'm trying to use mkl to compute a equation. But it seem that the array a[] leaks all the time lik this:
44.62 -0.09 -6277438562204192487878988888393020692503707483087375482269988814848.00 -6277438562204192487878988888393020692503707483087375482269988814848.00 -6277438562204192487878988888393020692503707483087375482269988814848.00
-0.09 11.29 -0.09 -6277438562204192487878988888393020692503707483087375482269988814848.00 -6277438562204192487878988888393020692503707483087375482269988814848.00
-6277438562204192487878988888393020692503707483087375482269988814848.00 -0.09 0.18 -0.09 -6277438562204192487878988888393020692503707483087375482269988814848.00
-6277438562204192487878988888393020692503707483087375482269988814848.00 -6277438562204192487878988888393020692503707483087375482269988814848.00 -0.09 11.29 -0.09
-6277438562204192487878988888393020692503707483087375482269988814848.00 -6277438562204192487878988888393020692503707483087375482269988814848.00 -6277438562204192487878988888393020692503707483087375482269988814848.00 -0.09 44.62
And my code is:
#include <stdlib.h>
#include <stdio.h>
#include "mkl_lapacke.h"
/* Auxiliary routines prototypes */
extern void my_print_matrix(char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda, FILE* fpWrite);
extern void print_matrix(char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda);
/* Parameters */
#define N 5//nstep
#define LDA N
#define RMIN -10.0
#define RMAX 10.0
/* Main program */
int main() {
/* Locals */
MKL_INT n = N, lda = LDA, info;
/* Local arrays */
double h = (RMAX - RMIN) / (double(N) + 1.0);;
double xi;
double *w;
double *a;
w= (double*)malloc(sizeof(double) * N);
a = (double*)malloc(sizeof(double) * N*LDA);
for (int i = 0; i < N; i++) {
xi = RMIN + double(1.0+i) * h;
a[i*(N+1)] = 2.0 / h / h+xi * xi;
if (i==0) {
a[1] = -1.0 / h / h;
}
else if (i == N - 1) {
a[LDA * N-2] =- 1.0 / h / h;
}
else {
a[i *(N + 1)+1] = -1.0/h/h;
a[i * (N + 1) - 1] = -1.0/h/h;
}
}
print_matrix("Matrix", n, n, a, lda);
/* Executable statements */
printf("LAPACKE_dsyev (row-major, high-level) Example Program Results\n");
/* Solve eigenproblem */
info = LAPACKE_dsyev(LAPACK_ROW_MAJOR, 'V', 'U', n, a, lda, w);
/* Check for convergence */
if (info > 0) {
printf("The algorithm failed to compute eigenvalues.\n");
exit(1);
}
exit(0);
} /* End of LAPACKE_dsyev Example */
/* Auxiliary routine: printing a matrix */
void print_matrix(char* desc, MKL_INT m, MKL_INT n, double* a, MKL_INT lda) {
MKL_INT i, j;
printf("\n %s\n", desc);
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) printf(" %6.2f", a[i * lda + j]);
printf("\n");
}
}
The first two elements is seem right but wrong numbers... And the last numbers are a same but very large number. I think it's array leaking,but I don't know how to deal with it. So I ask for help.
And the a[] show is just initialzed,not the result. My problem where is initializing wrong?

Lets take a closer look at how you initialize a:
a[i*(N+1)] = 2.0 / h / h+xi * xi;
if (i==0) {
a[1] = -1.0 / h / h;
}
else if (i == N - 1) {
a[LDA * N-2] =- 1.0 / h / h;
}
else {
a[i *(N + 1)+1] = -1.0/h/h;
a[i * (N + 1) - 1] = -1.0/h/h;
}
Lets take the two cases when i == 0 and i == 1:
i == 0
Here you first do the unconditional initialization
a[i*(N+1)] = 2.0 / h / h+xi * xi;
If we calculate the index i*(N+1) it's 0*(N+1) which is 0. Therefore you will initialize a[0].
Then you have if (i==0) where you initialize a[1].
i == 1
First the unconditional initialization of index i*(N+1), which then is 1*(50+1) which equals 51. So here you initialize a[51].
Then the conditions i==1 and i == N - 1 are both false, so we end up in the final else clause:
a[i *(N + 1)+1] = -1.0/h/h;
a[i * (N + 1) - 1] = -1.0/h/h;
The first index i *(N + 1)+1 will be 1 *(50 + 1)+1 which is 52. So you initialize a[52].
The next index i * (N + 1) - 1 will be 1 * (50 + 1) - 1 which is 50. So you initialize a[50].
This pattern repeats throughout the loop, with ever higher indexes, but never lower.
That means you will never initialize index 2 to 49. These elements will have indeterminate values, and if you're unlucky one of those values could be trap-values which would lead to undefined behavior when using them.
You need to rework your algorithm to initialize all elements of the array a.

regarding memory leakage - please don't forget to free all already allocated memory for *w and * arrays by calling free(a) and free(w) functions.

Related

Logistic regression code stops working above ~43,500 generated observations

Having some difficulty troubleshooting code I wrote in C to perform a logistic regression. While it seems to work on smaller, semi-randomized datasets, it stops working (e.g. assigning proper probabilities of belonging to class 1) at around the point where I pass 43,500 observations (determined by tweaking the number of observations created. When creating the 150 features used in the code, I do create the first two as a function of the number of observations, so I'm not sure if maybe that's the issue here, though I am using double precision. Maybe there's an overflow somewhere in the code?
The below code should be self-contained; it generates m=50,000 observations with n=150 features. Setting m below 43,500 should return "Percent class 1: 0.250000", setting to 44,000 or above will return "Percent class 1: 0.000000", regardless of what max_iter (number of times we sample m observations) is set to.
The first feature is set to 1.0 divided by the total number of observations, if class 0 (first 75% of observations), or the index of the observation divided by the total number of observations otherwise.
The second feature is just index divided by total number of observations.
All other features are random.
The logistic regression is intended to use stochastic gradient descent, randomly selecting an observation index, computing the gradient of the loss with the predicted y using current weights, and updating weights with the gradient and learning rate (eta).
Using the same initialization with Python and NumPy, I still get the proper results, even above 50,000 observations.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
// Compute z = w * x + b
double dlc( int n, double *X, double *coef, double intercept )
{
double y_pred = intercept;
for (int i = 0; i < n; i++)
{
y_pred += X[i] * coef[i];
}
return y_pred;
}
// Compute y_hat = 1 / (1 + e^(-z))
double sigmoid( int n, double alpha, double *X, double *coef, double beta, double intercept )
{
double y_pred;
y_pred = dlc(n, X, coef, intercept);
y_pred = 1.0 / (1.0 + exp(-y_pred));
return y_pred;
}
// Stochastic gradient descent
void sgd( int m, int n, double *X, double *y, double *coef, double *intercept, double eta, int max_iter, int fit_intercept, int random_seed )
{
double *gradient_coef, *X_i;
double y_i, y_pred, resid;
int idx;
double gradient_intercept = 0.0, alpha = 1.0, beta = 1.0;
X_i = (double *) malloc (n * sizeof(double));
gradient_coef = (double *) malloc (n * sizeof(double));
for ( int i = 0; i < n; i++ )
{
coef[i] = 0.0;
gradient_coef[i] = 0.0;
}
*intercept = 0.0;
srand(random_seed);
for ( int epoch = 0; epoch < max_iter; epoch++ )
{
for ( int run = 0; run < m; run++ )
{
// Randomly sample an observation
idx = rand() % m;
for ( int i = 0; i < n; i++ )
{
X_i[i] = X[n*idx+i];
}
y_i = y[idx];
// Compute y_hat
y_pred = sigmoid( n, alpha, X_i, coef, beta, *intercept );
resid = -(y_i - y_pred);
// Compute gradients and adjust weights
for (int i = 0; i < n; i++)
{
gradient_coef[i] = X_i[i] * resid;
coef[i] -= eta * gradient_coef[i];
}
if ( fit_intercept == 1 )
{
*intercept -= eta * resid;
}
}
}
}
int main(void)
{
double *X, *y, *coef, *y_pred;
double intercept;
double eta = 0.05;
double alpha = 1.0, beta = 1.0;
long m = 50000;
long n = 150;
int max_iter = 20;
long class_0 = (long)(3.0 / 4.0 * (double)m);
double pct_class_1 = 0.0;
clock_t test_start;
clock_t test_end;
double test_time;
printf("Constructing variables...\n");
X = (double *) malloc (m * n * sizeof(double));
y = (double *) malloc (m * sizeof(double));
y_pred = (double *) malloc (m * sizeof(double));
coef = (double *) malloc (n * sizeof(double));
// Initialize classes
for (int i = 0; i < m; i++)
{
if (i < class_0)
{
y[i] = 0.0;
}
else
{
y[i] = 1.0;
}
}
// Initialize observation features
for (int i = 0; i < m; i++)
{
if (i < class_0)
{
X[n*i] = 1.0 / (double)m;
}
else
{
X[n*i] = (double)i / (double)m;
}
X[n*i + 1] = (double)i / (double)m;
for (int j = 2; j < n; j++)
{
X[n*i + j] = (double)(rand() % 100) / 100.0;
}
}
// Fit weights
printf("Running SGD...\n");
test_start = clock();
sgd( m, n, X, y, coef, &intercept, eta, max_iter, 1, 42 );
test_end = clock();
test_time = (double)(test_end - test_start) / CLOCKS_PER_SEC;
printf("Time taken: %f\n", test_time);
// Compute y_hat and share of observations predicted as class 1
printf("Making predictions...\n");
for ( int i = 0; i < m; i++ )
{
y_pred[i] = sigmoid( n, alpha, &X[i*n], coef, beta, intercept );
}
printf("Printing results...\n");
for ( int i = 0; i < m; i++ )
{
//printf("%f\n", y_pred[i]);
if (y_pred[i] > 0.5)
{
pct_class_1 += 1.0;
}
// Troubleshooting print
if (i < 10 || i > m - 10)
{
printf("%g\n", y_pred[i]);
}
}
printf("Percent class 1: %f", pct_class_1 / (double)m);
return 0;
}
For reference, here is my (presumably) equivalent Python code, which returns the correct percent of identified classes at more than 50,000 observations:
import numpy as np
import time
def sigmoid(x):
return 1 / (1 + np.exp(-x))
class LogisticRegressor:
def __init__(self, eta, init_runs, fit_intercept=True):
self.eta = eta
self.init_runs = init_runs
self.fit_intercept = fit_intercept
def fit(self, x, y):
m, n = x.shape
self.coef = np.zeros((n, 1))
self.intercept = np.zeros((1, 1))
for epoch in range(self.init_runs):
for run in range(m):
idx = np.random.randint(0, m)
x_i = x[idx:idx+1, :]
y_i = y[idx]
y_pred_i = sigmoid(x_i.dot(self.coef) + self.intercept)
gradient_w = -(x_i.T * (y_i - y_pred_i))
self.coef -= self.eta * gradient_w
if self.fit_intercept:
gradient_b = -(y_i - y_pred_i)
self.intercept -= self.eta * gradient_b
def predict_proba(self, x):
m, n = x.shape
y_pred = np.ones((m, 2))
y_pred[:,1:2] = sigmoid(x.dot(self.coef) + self.intercept)
y_pred[:,0:1] -= y_pred[:,1:2]
return y_pred
def predict(self, x):
return np.round(sigmoid(x.dot(self.coef) + self.intercept))
m = 50000
n = 150
class1 = int(3.0 / 4.0 * m)
X = np.random.rand(m, n)
y = np.zeros((m, 1))
for obs in range(m):
if obs < class1:
continue
else:
y[obs,0] = 1
for obs in range(m):
if obs < class1:
X[obs, 0] = 1.0 / float(m)
else:
X[obs, 0] = float(obs) / float(m)
X[obs, 1] = float(obs) / float(m)
logit = LogisticRegressor(0.05, 20)
start_time = time.time()
logit.fit(X, y)
end_time = time.time()
print(round(end_time - start_time, 2))
y_pred = logit.predict(X)
print("Percent:", y_pred.sum() / len(y_pred))
The issue is here:
// Randomly sample an observation
idx = rand() % m;
... in light of the fact that the OP's RAND_MAX is 32767. This is exacerbated by the fact that all of the class 0 observations are at the end.
All samples will be drawn from the first 32768 observations, and when the total number of observations is greater than that, the proportion of class 0 observations among those that can be sampled is less than 0.25. At 43691 total observations, there are no class 0 observations among those that can be sampled.
As a secondary issue, rand() % m does not yield a wholly uniform distribution if m does not evenly divide RAND_MAX + 1, though the effect of this issue will be much more subtle.
Bottom line: you need a better random number generator.
At minimum, you could consider combining the bits from two calls to rand() to yield an integer with sufficient range, but you might want to consider getting a third-party generator. There are several available.
Note: OP reports "m=50,000 observations with n=150 features.", so perhaps this is not the issue for OP, but I'll leave this answer up for reference when OP tries larger tasks.
A potential issue:
long overflow
m * n * sizeof(double) risks overflow when long is 32-bit and m*n > LONG_MAX (or about 46,341 if m, n are the same).
OP does report
A first step is to perform the multiplication using size_t math where we gain at least 1 more bit in the calculation.
// m * n * sizeof(double)
sizeof(double) * m * n
Yet unless OP's size_t is more than 32-bit, we still have trouble.
IAC, I recommend to use size_t for array sizing and indexing.
Check allocations for failure too.
Since RAND_MAX may be too small and array indexing should be done using size_t math, consider a helper function to generate a random index over the entire size_t range.
// idx = rand() % m;
size_t idx = rand_size_t() % (size_t)m;
If stuck with the standard rand(), below is a helper function to extend its range as needed.
It uses the real nifty IMAX_BITS(m).
#include <assert.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
// https://stackoverflow.com/a/4589384/2410359
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
// Test that RAND_MAX is a power of 2 minus 1
_Static_assert((RAND_MAX & 1) && ((RAND_MAX/2 + 1) & (RAND_MAX/2)) == 0, "RAND_MAX is not a Mersenne number");
#define RAND_MAX_WIDTH (IMAX_BITS(RAND_MAX))
#define SIZE_MAX_WIDTH (IMAX_BITS(SIZE_MAX))
size_t rand_size_t(void) {
size_t index = (size_t) rand();
for (unsigned i = RAND_MAX_WIDTH; i < SIZE_MAX_WIDTH; i += RAND_MAX_WIDTH) {
index <<= RAND_MAX_WIDTH;
index ^= (size_t) rand();
}
return index;
}
Further considerations can replace the rand_size_t() % (size_t)m with a more uniform distribution.
As has been determined elsewhere, the problem is due to the implementation's RAND_MAX value being too small.
Assuming 32-bit ints, a slightly better PRNG function can be implemented in the code, such as this C implementation of the minstd_rand() function from C++:
#define MINSTD_RAND_MAX 2147483646
// Code assumes `int` is at least 32 bits wide.
static unsigned int minstd_seed = 1;
static void minstd_srand(unsigned int seed)
{
seed %= 2147483647;
// zero seed is bad!
minstd_seed = seed ? seed : 1;
}
static int minstd_rand(void)
{
minstd_seed = (unsigned long long)minstd_seed * 48271 % 2147483647;
return (int)minstd_seed;
}
Another problem is that expressions of the form rand() % m produce a biased result when m does not divide (unsigned int)RAND_MAX + 1. Here is an unbiased function that returns a random integer from 0 to le inclusive, making use of the minstd_rand() function defined earlier:
static int minstd_rand_max(int le)
{
int r;
if (le < 0)
{
r = le;
}
else if (le >= MINSTD_RAND_MAX)
{
r = minstd_rand();
}
else
{
int rm = MINSTD_RAND_MAX - le + MINSTD_RAND_MAX % (le + 1);
while ((r = minstd_rand()) > rm)
{
}
r /= (rm / (le + 1) + 1);
}
return r;
}
(Actually, it does still have a very small bias because minstd_rand() will never return 0.)
For example, replace rand() % 100 with minstd_rand_max(99), and replace rand() % m with minstd_rand_max(m - 1). Also replace srand(random_seed) with minstd_srand(random_seed).

Solving a coupled differential equations system using time splitting

/******************************************************************************
Online C Compiler.
Code, Compile, Run and Debug C program online.
Write your code in this editor and press "Run" button to compile and execute it.
*******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define PI 3.141592
void read_input(double *D, double *L, int *nx, double *t_F);
double main(void) {
/******************************/
/* Declarations of parameters */
/******************************/
/* Number of grid points */
int nx;
/* Length of domain */
double L;
/* Equation coefficients */
double D;
/* Length of time to run simulation. */
double t_F;
/* Read in from file; */
read_input(&D, &L, &nx, &t_F);
/* Grid spacing */
double dx = L/nx;
double invdx2 = 1.0/(dx*dx);
/* Time step */
double dt = 0.25/invdx2; // changed to 0.25/dx^2 to satisfy the stability condition
/************************************************/
/* Solution Storage at Current / Next time step */
/************************************************/
double *uc, *un, *vc, *vn;
/* Time splitting solutions */
double *uts1, *uts2, *vts1, *vts2;
/* Derivative used in finite difference */
double deriv;
/* Allocate memory according to size of nx */
uc = malloc(nx * sizeof(double));
un = malloc(nx * sizeof(double));
vc = malloc(nx * sizeof(double));
vn = malloc(nx * sizeof(double));
uts1 = malloc(nx * sizeof(double));
uts2 = malloc(nx * sizeof(double));
vts1 = malloc(nx * sizeof(double));
vts2 = malloc(nx * sizeof(double));
/* Check the allocation pointers */
if (uc==NULL||un==NULL||vc==NULL||vn==NULL||uts1==NULL||
uts2==NULL||vts1==NULL||vts2==NULL) {
printf("Memory allocation failed\n");
return 1;
}
int k;
double x;
/* Current time */
double ctime;
/* Initialise arrays */
for(k = 0; k < nx; k++) {
x = k*dx;
uc[k] = 1.0 + sin(2.0*PI*x/L);
vc[k] = 0.0;
/* Set other arrays to 0 */
uts1[k] = 0; uts2[k] = 0;
vts1[k] = 0; vts2[k] = 0;
}
/* Loop over timesteps */
while (ctime < t_F){
/* Rotation factors for time-splitting scheme. */
double cfac = cos(dt); //changed from 2*dt to dt
double sfac = sin(dt);
/* First substep for diffusion equation, A_1 */
for (k = 0; k < nx; k++) {
x = k*dx;
/* Diffusion at half time step. */
deriv = (uc[k-1] + uc[k+1] - 2*uc[k])*invdx2 ;
uts1[k] = uc[k] + (D * deriv + vc[k])* 0.5*dt; //
deriv = (vc[k-1] + vc[k+1] - 2*vc[k])*invdx2;
vts1[k] = vc[k] + (D * deriv - uc[k]) * 0.5*dt;
}
/* Second substep for decay/growth terms, A_2 */
for (k = 0; k < nx; k++) {
x = k*dx;
/* Apply rotation matrix to u and v, */
uts2[k] = cfac*uts1[k] + sfac*vts1[k];
vts2[k] = -sfac*uts1[k] + cfac*vts1[k];
}
/* Third substep for diffusion terms, A_1 */
for (k = 0; k < nx; k++) {
x = k*dx;
deriv = (uts2[k-1] + uts2[k+1] - 2*uts2[k])*invdx2;
un[k] = uts2[k] + (D * deriv + vts2[k]) * 0.5*dt;
deriv = (vts2[k-1] + vts2[k+1] - 2*vts2[k])*invdx2;
vn[k] = vts2[k] + (D * deriv - uts2[k]) * 0.5*dt;
}
/* Copy next values at timestep to u, v arrays. */
memcpy(uc,un, sizeof(double) * nx);
memcpy(vc,vn, sizeof(double) * nx);
/* Increment time. */
ctime += dt;
for (k = 0; k < nx; k++ ) {
x = k*dx;
printf("%g %g %g %g\n",ctime,x,uc[k],vc[k]);
}
}
/* Free allocated memory */
free(uc); free(un);
free(vc); free(vn);
free(uts1); free(uts2);
free(vts1); free(vts2);
return 0;
}
// The lines below don't contain any bugs! Don't modify them
void read_input(double *D, double *L, int *nx, double *t_F) {
FILE *infile;
if(!(infile=fopen("input.txt","r"))) {
printf("Error opening file\n");
exit(1);
}
if(4!=fscanf(infile,"%lf %lf %d %lf",D,L,nx,t_F)) {
printf("Error reading parameters from file\n");
exit(1);
}
fclose(infile);
}
So this is the code. It is meant to solve the following differential equations:
du/dt - Dd^2u/dx^2 - v = 0
dv/dt - Dd^2v/dx^2 + u = 0
It splits the equations into two parts. The second x derivative part(A1) and the decay part which contains u and v(A2) . It uses two half steps(0.5dt) for A1 and 1 full step of dt for A2. I know how to do time splitting but i dont know whether i have done it correctly here.
This is for an assignment and i have fixed all the errors and i am just trying to make the code work as intended. I have never had to solve something similar to this so i am definitely very stuck right now. The solution converges but i think its wrong. Any ideas why? Am not looking for someone to outright tell me what am doing wrong, just guide me in the right direction if you know what i mean.
PS: When i compile the code with gcc i get a warning about double main(void). Why might that be?

How to use GSL to fit an arbitrary function (i.e. 1/x + 1/x^2) to some data?

I have some data and I need to fit a second order "polynomial" in 1/x to it using C and GSL, but I don't really understand how to do it.
The documentation for GSL is, unfortunately, not very helpful, I have read it for a few hours now, but I don't seem to be getting closer to the solution.
Google doesn't turn up anything useful either, and I really don't know what to do anymore.
Could you maybe give me some hints on how to accomplish this, or where even to look?
Thanks
Edit 1: The main problem basically is that
Sum n : a_n*x^(-1)
is not a polynomial, so basic fitting or solving algorithms won't work correctly. That's what I tried, using the code for quadratic fitting from this link, also substituting x->1/x, but it didn't work.
May be it's a bit too late for you to read this. However, I post my answer anyway for other people looking for enlightenment.
I suppose, that this basic example can help you. First of all, you have to read about this method of non-linear fitting since you have to adapt the code for any of your own problem.
Second, it's a bit not really clear for me from your post what function you use.
For the sake of clarity let's consider
a1/x + a2/x**2
where a1 and a2 - your parameters.
Using that slightly modified code from the link above ( I replaced 1/x with 1/(x + 0.1) to avoid singularities but it doesn't really change the picture):
#include <stdlib.h>
#include <stdio.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlinear.h>
/* number of data points to fit */
#define N 40
#define FIT(i) gsl_vector_get(w->x, i)
#define ERR(i) sqrt(gsl_matrix_get(covar,i,i))
struct data
{
size_t n;
double * y;
};
int expb_f (const gsl_vector * x, void *data, gsl_vector * f)
{
size_t n = ((struct data *)data)->n;
double *y = ((struct data *)data)->y;
double A_1 = gsl_vector_get (x, 0);
double A_2 = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Model Yi = A_1 / x + A_2 / x**2 */
double t = i;
double Yi = A_1 / (t + 0.1) +A_2 / (t*t + 0.2*t + 0.01) ;
gsl_vector_set (f, i, Yi - y[i]);
}
return GSL_SUCCESS;
}
int expb_df (const gsl_vector * x, void *data, gsl_matrix * J)
{
size_t n = ((struct data *)data)->n;
double A_1 = gsl_vector_get (x, 0);
double A_2 = gsl_vector_get (x, 1);
size_t i;
for (i = 0; i < n; i++)
{
/* Jacobian matrix J(i,j) = dfi / dxj, */
/* where fi = (Yi - yi)/sigma[i], */
/* Yi = A_1 / (t + 0.1) +A_2 / (t*t + 0.2*t + 0.01) */
/* and the xj are the parameters (A_1,A_2) */
double t = i;
double e = 1 / (t + 0.1);
double e1 = 1 / (t*t + 0.2*t + 0.01);
gsl_matrix_set (J, i, 0, e);
gsl_matrix_set (J, i, 1, e1);
}
return GSL_SUCCESS;
}
void callback(const size_t iter, void *params, const gsl_multifit_nlinear_workspace *w)
{
gsl_vector *f = gsl_multifit_nlinear_residual(w);
gsl_vector *x = gsl_multifit_nlinear_position(w);
double rcond;
/* compute reciprocal condition number of J(x) */
gsl_multifit_nlinear_rcond(&rcond, w);
fprintf(stderr, "iter %2zu: A_1 = % e A_2 = % e cond(J) = % e, |f(x)| = % e \n", iter, gsl_vector_get(x, 0), gsl_vector_get(x, 1), 1.0 / rcond, gsl_blas_dnrm2(f));
}
int main (void)
{
const gsl_multifit_nlinear_type *T = gsl_multifit_nlinear_trust;
gsl_multifit_nlinear_workspace *w;
gsl_multifit_nlinear_fdf fdf;
gsl_multifit_nlinear_parameters fdf_params = gsl_multifit_nlinear_default_parameters();
const size_t n = N;
const size_t p = 2;
gsl_vector *f;
gsl_matrix *J;
gsl_matrix *covar = gsl_matrix_alloc (p, p);
double y[N], weights[N];
struct data d = { n, y };
double x_init[2] = { 1.0, 1.0 }; /* starting values */
gsl_vector_view x = gsl_vector_view_array (x_init, p);
gsl_vector_view wts = gsl_vector_view_array(weights, n);
gsl_rng * r;
double chisq, chisq0;
int status, info;
size_t i;
const double xtol = 1e-8;
const double gtol = 1e-8;
const double ftol = 0.0;
gsl_rng_env_setup();
r = gsl_rng_alloc(gsl_rng_default);
/* define the function to be minimized */
fdf.f = expb_f;
fdf.df = expb_df; /* set to NULL for finite-difference Jacobian */
fdf.fvv = NULL; /* not using geodesic acceleration */
fdf.n = n;
fdf.p = p;
fdf.params = &d;
/* this is the data to be fitted */
for (i = 0; i < n; i++)
{
double t = i;
double yi = (0.1 + 3.2/(t + 0.1))/(t + 0.1);
double si = 0.1 * yi;
double dy = gsl_ran_gaussian(r, si);
weights[i] = 1.0 / (si * si);
y[i] = yi + dy;
printf ("% e % e \n",t + 0.1, y[i]);
};
/* allocate workspace with default parameters */
w = gsl_multifit_nlinear_alloc (T, &fdf_params, n, p);
/* initialize solver with starting point and weights */
gsl_multifit_nlinear_winit (&x.vector, &wts.vector, &fdf, w);
/* compute initial cost function */
f = gsl_multifit_nlinear_residual(w);
gsl_blas_ddot(f, f, &chisq0);
/* solve the system with a maximum of 20 iterations */
status = gsl_multifit_nlinear_driver(20, xtol, gtol, ftol, callback, NULL, &info, w);
/* compute covariance of best fit parameters */
J = gsl_multifit_nlinear_jac(w);
gsl_multifit_nlinear_covar (J, 0.0, covar);
/* compute final cost */
gsl_blas_ddot(f, f, &chisq);
fprintf(stderr, "summary from method '%s/%s'\n", gsl_multifit_nlinear_name(w), gsl_multifit_nlinear_trs_name(w));
fprintf(stderr, "number of iterations: %zu \n", gsl_multifit_nlinear_niter(w));
fprintf(stderr, "function evaluations: %zu \n", fdf.nevalf);
fprintf(stderr, "Jacobian evaluations: %zu \n", fdf.nevaldf);
fprintf(stderr, "reason for stopping: %s \n", (info == 1) ? "small step size" : "small gradient");
fprintf(stderr, "initial |f(x)| = % e \n", sqrt(chisq0));
fprintf(stderr, "final |f(x)| = % e \n", sqrt(chisq));
{
double dof = n - p;
double c = GSL_MAX_DBL(1, sqrt(chisq / dof));
fprintf(stderr, "chisq/dof = % e \n", chisq / dof);
fprintf (stderr, "A_1 = % f +/- % f \n", FIT(0), c*ERR(0));
fprintf (stderr, "A_2 = % f +/- % f \n", FIT(1), c*ERR(1));
}
fprintf (stderr, "status = %s \n", gsl_strerror (status));
gsl_multifit_nlinear_free (w);
gsl_matrix_free (covar);
gsl_rng_free (r);
return 0;
}
Results of simulations
Unfortunately, Gnuplot doesn't want to fit this data for some reason. Usually it gives the same function up to certain decimal numbers and helps to verify your code.

The outermost for loop does not work as intended

I have been using Ubuntu 12.04 LTS with GCC to compile my the codes for my assignment for a while. However, recently I have run into two issues as follows:
The following code calculates zero for a nonzero value with the second formula is used.
There is a large amount of error in the calculation of the integral of the standard normal distribution from 0 to 5 or larger standard deviations.
How can I remedy these issues? I am especially obsessed with the first one. Any help or suggestion is appreciated. thanks in advance.
The code is as follows:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 599
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int p = 0, k, z[5] = {0, 3, 5, 10, 20};
long double sum1[5] = {0}, sum2[5] = {0} , factor = 1.0;
for (p = 0; p <= 4; p++)
{
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z[p], 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1[p] += summand1[k];
}
//Wolfamalpha site gives the same value here
for (k = 0; k <= N; k++)
{
factor *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) ) * powl(z[p], 2 * k + 1) / factor);
//printf("%Le \n", factor);
sum2[p] += summand2[k];
}
sum2[p] = sum2[p] * expl((-powl(z[p],2)) / 2);
}
for (p = 0; p < 4; p++)
{
printf("The sum obtained for z between %d - %d \
\nusing the first formula is %Lf \n", z[p], z[p+1], sum1[p+1]);
printf("The sum obtained for z between %d - %d \
\nusing the second formula is %Lf \n", z[p], z[p+1], sum2[p+1]);
}
return 0;
}
The working code without the outermost for loop is
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define N 1200
long double
factorial(long double n)
{
//Here s is the free parameter which is increased by one in each step and
//pro is the initial product and by setting pro to be 0 we also cover the
//case of zero factorial.
int s = 1;
long double pro = 1;
//Here pro stands for product.
if (n < 0)
printf("Factorial is not defined for a negative number \n");
else {
while (n >= s) {
pro *= s;
s++;
}
return pro;
}
}
int main()
{
// Since the function given is the standard normal distribution
// probability density function we have mean = 0 and variance = 1.
// Hence we also have z = x; while dealing with only positive values of
// x and keeping in mind that the PDF is symmetric around the mean.
long double * summand1 = malloc(N * sizeof(long double));
long double * summand2 = malloc(N * sizeof(long double));
int k, z = 3;
long double sum1 = 0, sum2 = 0, pro = 1.0;
for (k = 0; k <= N; k++)
{
summand1[k] = (1 / sqrtl(M_PI * 2) )* powl(-1, k) * powl(z, 2 * k + 1) / ( factorial(k) * (2 * k + 1) * powl(2, k));
sum1 += summand1[k];
}
//Wolfamalpha site gives the same value here
printf("The sum obtained for z between 0-3 using the first formula is %Lf \n", sum1);
for (k = 0; k <= N; k++)
{
pro *= (2 * k + 1);
summand2[k] = ((1 / sqrtl(M_PI * 2) * powl(z, 2 * k + 1) / pro));
//printf("%Le \n", pro);
sum2 += summand2[k];
}
sum2 = sum2 * expl((-powl(z,2)) / 2);
printf("The sum obtained for z between 0-3 using the second formula is %Lf \n", sum2);
return 0;
}
I'm quite certain that the problem is in factor not being set back to 1 in the outer loop..
factor *= (2 * k + 1); (in the loop that calculates sum2.)
In the second version provided the one that works it starts with z=3
However in the first loop since you do not clear it between iterations on p by the time you reach z[2] it already is a huge number.
EDIT: Possible help with precision..
Basically you have a huge number powl(z[p], 2 * k + 1) divided by another huge number factor. huge floating point numbers lose their precision. The way to avoid that is to perform the division as soon as possible..
Instead of first calculating powl(z[p], 2 * k + 1) and dividing by factor :
- (z[p]z[p] ... . * z[p]) / (1*3*5*...(2*k+1))`
rearrange the calculation: (z[p]/1) * (z[p]^2/3) * (z[p]^2/5) ... (z[p]^2/(2*k+1))
You can do this in sumand2 calculation and a similar trick in summand1

Doesn't move and rotate the triangle around a point - C Bgi graphics

Greeting,
I have this graphic homework in BGI graphic. We must use DevCPP and BGI, and matrices.
I wrote this code, and I think the transformations is good. But my triangle doesn't move and rotate around the circle, And I don't understand, why not it moves around the circle...
I don't know where and what I have to rewrite.
#include <math.h>
#include "graphics.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#define PI 3.14159265
typedef float Matrix3x3[3][3];
Matrix3x3 theMatrix;
int Round( double n ){
return (int)( n + 0.5 );
}
void matrix3x3SetIdentity(Matrix3x3 m)
{
int i, j;
for(i=0; i<3; i++)
for(j=0; j<3;j++)
m[i][j]=(i==j);
}
/* Multiplies matrix, result in b matrix */
void matrix3x3PreMultiply(Matrix3x3 a, Matrix3x3 b)
{
int r, c;
Matrix3x3 tmp;
for(r=0; r<3;r++)
for(c=0; c<3;c++)
tmp[r][c]=
a[r][0]*b[0][c]+a[r][1]*b[1][c]+a[r][2]*b[2][c];
for(r=0; r<3;r++)
for(c=0; c<3; c++)
b[r][c]-tmp[r][c];
}
void translate2(int tx, int ty)
{
Matrix3x3 m;
matrix3x3SetIdentity (m);
m[0][2] = tx;
m[1][2] = ty;
matrix3x3PreMultiply(m, theMatrix);
}
void scale2 (float sx, float sy, pont2d refpt)
{
Matrix3x3 m;
matrix3x3SetIdentity(m);
m[0][0]=sx;
m[0][2]=(1-sx)*refpt.x;
m[1][1]=sy;
m[1][2]=(1-sy)*refpt.y;
matrix3x3PreMultiply(m, theMatrix);
}
void rotate2 (float a, pont2d refpt)
{
Matrix3x3 m;
matrix3x3SetIdentity(m);
a=a/PI;
m[0][0] = cosf(a);
m[0][1] = -sinf(a);
m[0][2] = refpt.x * (1-cosf(a)) + refpt.y * sinf(a);
m[1][0] = sinf (a);
m[1][1] = cosf (a);
m[1][2] = refpt.y * (1-cosf(a)) - refpt.x * sinf(a);
matrix3x3PreMultiply(m, theMatrix);
}
void transformPoints2 (int npts, pont2d *pts)
{
int k;
float tmp;
for (k = 0; k < npts; k++) {
tmp = theMatrix[0][0] * pts[k].x + theMatrix[0][1] *
pts[k].y + theMatrix[0][2];
pts[k].y = theMatrix[1][0] * pts[k].x + theMatrix[1][1] *
pts[k].y + theMatrix[1][2];
pts[k].x = tmp;
}
}
int main()
{
int gd, gm, i, page=0;
gd=VGA;gm=VGAHI;
initgraph(&gd,&gm,"");
int ap;
while(!kbhit())
{
setactivepage(page);
cleardevice();
pont2d P[3] = { 50.0, 50.0, 150.0, 50.0, 100.0, 150.0};
pont2d refPt = {200.0, 250.0};
// Drawing the Triangle
moveto( Round( P[ 0 ].x ), Round( P[ 0 ].y ) );
for( i = 1; i < 3; i++ )
lineto( Round( P[ i ].x ), Round( P[ i ].y ) );
lineto( Round( P[ 0 ].x ), Round( P[ 0 ].y ) );
// Drawing the Circle
fillellipse(200, 250, 5,5);
setcolor (BLUE);
matrix3x3SetIdentity (theMatrix);
scale2 (0.5, 0.5, refPt);
//scale2 (20, 20, refPt);
rotate2 (90.0, refPt);
translate2 (0, 150);
transformPoints2 (3, P);
setvisualpage(page);
page = 1-page;
}
getch();
closegraph();
return 0;
}
If you want to see the object "spin", then rotations should be performed about the local origin. Rotation about the global origin will cause the object to "orbit" the global origin. Thus, to spin the object:
Translate the object to global origin
Apply the rotation
Translate the object back to its original position
Look at the discussion regarding transformation order here for an illustration. Specifically, look for the section entitled "Demonstration of the importance of transformation order".
To rotate a triangle, get the three points and use the formula:
x' = x + r cos (theta)
y' = y - r sin (theta)
The above formula can be applied into a loop where there being 0 to 360. You can have a graphics simulation by putting a delay (200) milliseconds in the loop.

Resources