1 /* *******************************************************************
2 FILE:		recipes.c
3 DESCRIPTION:	Routines for vector and matrix allocation/free.
4 		Linear system solving by LU decomposition.
5 		All are from "Numerical Recipes in C".
6 
7 CONTAINTS:
8 		double  *vector(nl,nh)
9 		int    nl,nh;
10 
11 		int  *ivector(nl,nh)
12 		int  nl,nh;
13 
14 		void free_vector(v,nl,nh)
15 		double *v;
16 		int   nl,nh;
17 
18 		void free_ivector(v,nl,nh)
19 		int *v;
20 		int   nl,nh;
21 
22 		double  **matrix(nrl,nrh,ncl,nch)
23 		int  nrl,nrh,ncl,nch;
24 
25 		void free_matrix(m,nrl,nrh,ncl,nch)
26 		double **m;
27 		int   nrl,nrh,ncl,nch;
28 
29 		nrerror(error_text)
30 		char error_text[];
31 
32 		void ludcmp(a,n,indx,d)
33 		int n, *indx;
34 		double **a,*d;
35 
36 		void lubksb(a,n,indx,b)
37 		double **a,b[];
38 		int n,indx[];
39 
40 DATE:
41 AUTHOR:		From "Numerical Recipes in C"
42 REVISIONS:	February 01, 1994: File created.
43 		Febryary 24, 2000:
44 			This file is taken out from my PhD sources, Srdjan.
45 			Unnecessary functions are removed.
46 			All floats are converted to doubles.
47   ********************************************************************* */
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <math.h>
51 #include "recipes.h"
52 
53 #define TINY 1.0e-20
54 
55 void nrerror(char * error_text);
56 
57 /*****************************************************/
58 /*** Allocates a double vector with range [nl..nh]. ***/
59 /*****************************************************/
vector(nl,nh)60 double  *vector(nl,nh)
61 int    nl,nh;
62 {
63 	double *v;
64 
65 	v = (double *) malloc((unsigned) (nh-nl+1)*sizeof(double));
66 	if (!v) nrerror("Allocation failure in vector().\n");
67 	return (v-nl);
68 }
69 
70 /*****************************************************/
71 /*** Allocates an int vector with range [nl..nh].  ***/
72 /*****************************************************/
ivector(nl,nh)73 int  *ivector(nl,nh)
74 int  nl,nh;
75 {
76 	int *v;
77 
78 	v = (int *) calloc((unsigned) (nh-nl+1),sizeof(int));
79 	if (!v) nrerror("Allocation failure in vector().\n");
80 	return (v-nl);
81 }
82 
83 /****************************************************/
84 /*** Frees a double vector allocated by vector().  ***/
85 /****************************************************/
free_vector(v,nl,nh)86 void free_vector(v,nl,nh)
87 double *v;
88 int   nl,nh;
89 {
90 	free((char*) (v+nl));
91 }
92 
93 /****************************************************/
94 /*** Frees an int vector allocated by ivector().  ***/
95 /****************************************************/
free_ivector(v,nl,nh)96 void free_ivector(v,nl,nh)
97 int *v;
98 int   nl,nh;
99 {
100 	free((char*) (v+nl));
101 }
102 
103 /*******************************************/
104 /****  Allocates a double matrix with    ****/
105 /****  range [nrl..nrh] [ncl..nch].     ****/
106 /*******************************************/
matrix(nrl,nrh,ncl,nch)107 double  **matrix(nrl,nrh,ncl,nch)
108 int  nrl,nrh,ncl,nch;
109 {
110 	int    i;
111 	double  **m;
112 
113 	/*** Allocate pointers to rows.   ****/
114 	m = (double**) calloc((unsigned) (nrh-nrl+1),sizeof(double*));
115 	if (!m) nrerror("Allocation failure #1 in matrix().");
116 	m -= nrl;
117 
118 
119 	/***  Allocate rows and pointers to them.  ***/
120 	for (i=nrl; i<=nrh; i++)  {
121 		m[i] = (double *) malloc((unsigned) (nch-ncl+1)*sizeof(double));
122 		if (!m[i]) nrerror("Allocation failure #2 in matrix().");
123 		m[i] -= ncl;
124 	}
125 	return(m);
126 }
127 
128 /******************************************/
129 /****   Frees a matrix allocated by ... ***/
130 /****   matrix().                       ***/
131 /******************************************/
free_matrix(m,nrl,nrh,ncl,nch)132 void free_matrix(m,nrl,nrh,ncl,nch)
133 double **m;
134 int   nrl,nrh,ncl,nch;
135 {
136 	int i;
137 
138 	for (i=nrh; i>=nrl; i--)  free((char*) (m[i]+ncl));
139 	free ((char*) (m+nrl));
140 }
141 
142 /*************************************************/
143 /*** Numerical Recipes standard error handler. ***/
144 /*************************************************/
nrerror(error_text)145 void nrerror(error_text)
146 char error_text[];
147 {
148 	void exit();
149 
150 	fprintf(stderr,"Numerical Recipes run-time error...\n");
151 	fprintf(stderr,"%s\n",error_text);
152 	fprintf(stderr,"Forced to exit.\n");
153 	exit(1);
154 }
155 
156 /* ******************************************************************** */
157 /* LU Decomposition of a matrix						*/
158 /*	a[1:n][1:n]		system matrix,				*/
159 /*	n			problem dimension,			*/
160 /*	indx[1:n]		temporary storage,			*/
161 /*	d			temporary storage.			*/
162 /* ******************************************************************** */
ludcmp(a,n,indx,d)163 int ludcmp(a,n,indx,d)
164 int n, *indx;
165 double **a,*d;
166 {
167 	int i,imax,j,k;
168 	double big,dum,sum,temp;
169 	double *vv,*vector();
170 	void free_vector();
171 
172 	imax = 0;
173 
174 	vv=vector(1,n);
175 	(*d)=1.0;
176 	for (i=1;i<=n;i++) {
177 		big=0.0;
178 		for (j=1;j<=n;j++)
179 			if ((temp=fabs(a[i][j])) > big) big=temp;
180 		if (!big) nrerror("Singular matrix in routine LUDCMP");
181 		vv[i]=1.0/big;
182 	}
183 	for (j=1;j<=n;j++) {
184 		for (i=1;i<j;i++) {
185 			sum=a[i][j];
186 			for (k=1;k<i;k++) sum -= a[i][k]*a[k][j];
187 			a[i][j]=sum;
188 		}
189 		big=0.0;
190 		for (i=j;i<=n;i++) {
191 			sum=a[i][j];
192 			for (k=1;k<j;k++)
193 				sum -= a[i][k]*a[k][j];
194 			a[i][j]=sum;
195 			if ((dum=vv[i]*fabs(sum))>=big) {
196 				big=dum;
197 				imax=i;
198 			}
199 		}
200 		if (j!=imax) {
201 			for (k=1;k<=n;k++) {
202 				dum=a[imax][k];
203 				a[imax][k]=a[j][k];
204 				a[j][k]=dum;
205 			}
206 			(*d)= -(*d);
207 			vv[imax]=vv[j];
208 		}
209 		indx[j]=imax;
210 		if(fpclassify(a[j][j]) == FP_ZERO) {
211 			a[j][j]=TINY;
212 		}
213 		if (j!=n) {
214 			dum=1.0/(a[j][j]);
215 			for (i=j+1;i<=n;i++) a[i][j] *= dum;
216 		}
217         }
218 	free_vector(vv,1,n);
219 	return(0);
220 
221 } /* end of ludcmp() */
222 
223 /* ******************************************************************** */
224 /* Solve system of equation						*/
225 /* ******************************************************************** */
lubksb(a,n,indx,b)226 void lubksb(a,n,indx,b)
227 double **a,b[];
228 int n,indx[];
229 {
230 	int i,ii=0,ip,j;
231 	double sum;
232 
233 	for (i=1;i<=n;i++) {
234 		ip=indx[i];
235 		sum=b[ip];
236 		b[ip]=b[i];
237 		if (ii) {
238 			for (j=ii;j<=i-1;j++) sum -= a[i][j]*b[j];
239 		} else if (sum) {
240 			ii=i;
241 		}
242 		b[i]=sum;
243 	}
244 	for (i=n;i>=1;i--) {
245 		sum=b[i];
246 		for (j=i+1;j<=n;j++) sum -= a[i][j]*b[j];
247 		b[i]=sum/a[i][i];
248 	}
249 
250 }   /*  end of lubksb() */
251 
252