nurb_solve.c

Go to the documentation of this file.
00001 /** @addtogroup nurb */
00002 /*@{*/
00003 /** @file nurb_solve.c
00004  * Decompose a matrix into its LU decomposition using pivoting.
00005  *
00006  * Author:      Paul R. Stay
00007  *              Computer Science Dept.
00008  *              University of Utah
00009  * Date:        Wed Mar 23 1983
00010  * Copyright (c) 1983, University of Utah
00011  *
00012  */
00013 /*@}*/
00014 
00015 #include "common.h"
00016 
00017 
00018 
00019 #include <stdio.h>
00020 #include <math.h>
00021 #include "machine.h"
00022 #include "vmath.h"
00023 #include "raytrace.h"
00024 #include "nurb.h"
00025 
00026 /* These Procedures take a set of matrices of the form Ax = b and
00027  * alows one to solve the system by various means. The rt_nurb_doolittle
00028  * routine takes the system and creates a lu decomposition using
00029  * pivoting  to get the system in a desired form. Forward and backward
00030  * substitution are then used to solve the system.  All work is done
00031  * in place.
00032  */
00033 
00034 /* Solve must be passed two matrices that are of the form of pointer
00035  * to double arrays. mat_1 is the n by n matrix that is to be
00036  * decomposed and mat_2 is the matrix that contains the left side of
00037  * the equation.  The variable solution which is double is also to be
00038  * created by the user and consisting of n elements of which the
00039  * solution set is passed back.
00040  *
00041  *  Arguments mat_1 and mat_2 are modified by this call.
00042  *  The solution is written into the solution[] array.
00043  */
00044 void
00045 rt_nurb_solve(fastf_t *mat_1, fastf_t *mat_2, fastf_t *solution, int dim, int coords)
00046                         /* A and b array of the system Ax= b*/
00047 
00048 
00049                         /* dimension of the matrix */
00050                         /* Number of coordsinates for mat_2 and solution */
00051 {
00052         register int i, k;
00053         fastf_t *y;
00054         fastf_t * b;
00055         fastf_t * s;
00056 
00057         y = (fastf_t *) bu_malloc(sizeof (fastf_t) * dim,
00058             "rt_nurb_solve: y");/* Create temp array */
00059 
00060         b = (fastf_t *) bu_malloc(sizeof (fastf_t) * dim,
00061             "rt_nurb_solve: b");/* Create temp array */
00062 
00063         s = (fastf_t *) bu_malloc(sizeof (fastf_t) * dim,
00064             "rt_nurb_solve: s");/* Create temp array */
00065 
00066         rt_nurb_doolittle (mat_1,mat_2, dim, coords);/* Create LU decomosition */
00067 
00068         for( k =0; k < coords; k++)
00069         {
00070                 fastf_t * ptr;
00071 
00072                 ptr = mat_2 + k;
00073 
00074                 for( i = 0; i < dim; i++)
00075                 {
00076                         b[i] = *ptr;
00077                         ptr += coords;
00078                 }
00079 
00080                 /* Solve the system Ly =b */
00081                 rt_nurb_forw_solve (mat_1, b, y, dim);
00082 
00083                 /* Solve the system Ux = y */
00084                 rt_nurb_back_solve (mat_1, y, s, dim);
00085 
00086 
00087                 ptr = solution + k;
00088                 for( i=0; i < dim; i++)
00089                 {
00090                         *ptr = s[i];
00091                         ptr += coords;
00092                 }
00093         }
00094 
00095         bu_free ((char *)y,"rt_nurb_solve: y");                 /* Free up storage */
00096         bu_free ((char *)b,"rt_nurb_solve: b");                 /* Free up storage */
00097         bu_free ((char *)s,"rt_nurb_solve: s");                 /* Free up storage */
00098 }
00099 
00100 /*
00101  *  Create LU decomosition.
00102  *  Modifies both mat_1 and mat_2 values.
00103  */
00104 void
00105 rt_nurb_doolittle(fastf_t *mat_1, fastf_t *mat_2, int row, int coords)
00106 {
00107         register int i;
00108         register int j;
00109         register int k;
00110         register int x;
00111         int m;
00112         register fastf_t *d;            /* Scaling factors */
00113         register fastf_t *s;            /* vector for swapping if needed */
00114         register fastf_t *ds;           /* See if swapping is needed */
00115         fastf_t  maxd;
00116         fastf_t tmp;
00117 
00118         int     max_pivot;
00119 
00120         d = (fastf_t * ) bu_malloc( sizeof (fastf_t) * row,
00121             "rt_nurb_doolittle:d");     /* scale factor */
00122         s = (fastf_t * ) bu_malloc( sizeof (fastf_t) * row * row,
00123             "rt_nurb_doolittle:s");     /* vector to check */
00124         ds = (fastf_t *) bu_malloc( sizeof (fastf_t) * row,
00125             "rt_nurb_doolittle:ds");    /* if rows need to be swaped */
00126 
00127         for ( i = 0; i < row; i++)              /* calculate the scaling factors */
00128         {
00129                 maxd = 0.0;
00130                 for( j = 0; j < row; j++)
00131                 {
00132                         if( maxd < fabs(mat_1[i * row + j]) )
00133                                 maxd = fabs(mat_1[i * row + j]);
00134                 }
00135                 d[i] = 1.0 / maxd;
00136         }
00137 
00138         for ( k = 0 ; k < row; k++)
00139         {
00140                 for( i = k; i < row; i++)
00141                 {
00142                         tmp = 0.0;
00143                         for( j = 0; j <= k -1; j ++)
00144                                 tmp += mat_1[i * row + j ] * mat_1[j * row + k];
00145                         s[i * row + k] = mat_1[i * row + k] - tmp;
00146                 }
00147 
00148                 max_pivot = k;
00149 
00150                 for (i = k; i < row; i ++)      /* check to see if rows need */
00151                 {                               /* to be swaped */
00152                         ds[i] = d[i] * s[ i * row + k];
00153                         if (ds[max_pivot] < ds[i])
00154                                 max_pivot = i;
00155                 }
00156 
00157                 if (max_pivot != k )            /* yes swap row k with row max_pivot */
00158                 {
00159                         for( m = 0; m < row; m++)
00160                         {
00161                                 tmp = mat_1[k * row + m];
00162                                 mat_1[k * row + m] = mat_1[max_pivot * row + m];
00163                                 mat_1[max_pivot * row + m] = tmp;
00164                         }
00165 
00166                         for( x = 0; x < coords; x++)
00167                         {
00168                                 tmp = mat_2[k*coords + x];              /* b matrix also */
00169                                 mat_2[k*coords+x] = mat_2[max_pivot*coords+x];
00170                                 mat_2[max_pivot*coords+x] = tmp;
00171                         }
00172 
00173                         tmp = s[k * row + k];   /* swap s vector  */
00174                         s[k * row + k] = s[max_pivot * row + k];
00175                         s[max_pivot * row + k] = tmp;
00176                 }
00177 
00178                 mat_1[ k * row +  k] = s[k * row + k];  /* mat_1[k][k] */
00179 
00180                 for (i = k + 1; i < row; i++)   /* lower matrix */
00181                         mat_1[i * row + k] = (float)(s[i* row + k] / s[k* row +k]);
00182 
00183                 for (j = k + 1; j < row; j++) { /* upper matrix */
00184                         tmp = 0;
00185                         for( i = 0; i <= k - 1; i++)
00186                                 tmp += mat_1[ k * row + i] * mat_1[ i* row + j];
00187 
00188                         mat_1[ k * row + j] -= tmp;
00189                 }
00190 
00191         }
00192         bu_free( (char *)d,"rt_nurb_doolittle:d");              /* Free up the storage. */
00193         bu_free( (char *)s,"rt_nurb_doolittle:s");
00194         bu_free( (char *)ds,"rt_nurb_doolittle:ds" );
00195 }
00196 
00197 void
00198 rt_nurb_forw_solve(const fastf_t *lu, const fastf_t *b, fastf_t *y, int n)              /* spl_solve lower trianglular matrix */
00199 
00200 
00201 
00202 
00203 {
00204         register int i,j;
00205         fastf_t tmp;
00206 
00207         for(i = 0; i < n; i++)
00208         {
00209                 tmp = 0.0;
00210                 for(j = 0; j <= i - 1; j++)
00211                         tmp += lu[i*n + j] * y[j];
00212                 y[i] = b[i] - tmp;
00213         }
00214 }
00215 
00216 void
00217 rt_nurb_back_solve(const fastf_t *lu, const fastf_t *y, fastf_t *x, int n)              /* spl_solve upper triangular matrix */
00218 
00219 
00220 
00221 
00222 {
00223         register int i,j;
00224         fastf_t tmp;
00225 
00226         for( i = n - 1; i >= 0; i-- )
00227         {
00228                 tmp = 0.0;
00229                 for( j = i + 1; j < n; j++)
00230                         tmp += lu[i*n + j] * x[j];
00231                 x[i] = ( y[i] - tmp) / lu[i * n + i];
00232         }
00233 
00234 }
00235 
00236 void
00237 rt_nurb_p_mat(const fastf_t *mat, int dim)
00238 {
00239         int i;
00240 
00241         for( i = 0; i < dim; i++)
00242                 fprintf(stderr,"%f\n", mat[i]);
00243         fprintf(stderr,"\n");
00244 }
00245 
00246 /*
00247  * Local Variables:
00248  * mode: C
00249  * tab-width: 8
00250  * c-basic-offset: 4
00251  * indent-tabs-mode: t
00252  * End:
00253  * ex: shiftwidth=4 tabstop=8
00254  */

Generated on Mon Sep 18 01:24:55 2006 for BRL-CAD by  doxygen 1.4.6