OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
imsl_d_lin_sol_gen.c
Go to the documentation of this file.
1 /*
2 $Log: imsl_d_lin_sol_gen.c,v $
3 Revision 4.3 2003/08/28 16:04:04 kuyper
4 Corrected prolog.
5 
6 Revision 4.2 2003/07/31 20:56:20 kuyper
7 Corrected some loop boundary errors.
8 Replaced incorrect test for ill-condition matrix in ludcmp3() with a more
9  correct estimate in imsl_d_lin_sol_gen().
10 Changed to scale singular rows by 0.0.
11 
12 Revision 4.1 2003/07/27 20:59:53 kuyper
13 Initial revision.
14 
15 James Kuyper Jr. (kuyper@saicmodis.com)
16  */
17 #include <math.h>
18 #include <string.h>
19 #include <stdarg.h>
20 #include <float.h>
21 #include "imsl_wrap.h"
22 #include "pseudo_imsl.h"
23 #define THREED 3
24 #define TINY 1.0E-99
25 
26 static void ludcmp3(
27  double a[THREED][THREED],
28  int indx[THREED],
29  double *d
30 ){
31 /******************************************************************************
32 !C
33 
34 !Description:
35  Replaces the THREED by THREED array 'a' with an L/U decomposition of
36  itself. This function may be used in combination with lubksb3() to
37  solve linear equations.
38 
39 !Input Parameters:
40  None
41 
42 !Output Parameters:
43  indx The permutation of the rows that was performed as a result of
44  partial pivoting
45  d +/- 1, depending upon whether the number of row interchanges
46  in indx is even or odd.
47 
48 !Input/Output Parameters:
49  a On input, the two-dimensional array to be decomposed. On output,
50  the elements of that array below the diagonal are the non-zero
51  off-diagonal elements of the array L, and the elements on and
52  above the diagonal are the non-zero elements of the array U,
53  with the diagonal elements of L being 1.0, such that A = L*U.
54 
55 Return Parameters:
56  None.
57 
58 Externally Defined:
59  IMSL_error_code "pseudo_imsl.h"
60  IMSL_SINGULAR_MATRIX "imsl_wrap.h"
61  THREED "imsl_d_lin_sol_gen.c"
62 
63 Called by:
64  imsl_d_lin_sol_gen
65 
66 Routines Called:
67  None
68 
69 !Revision History:
70 See top of file.
71 
72 Requirements:
73  None
74 
75 !Team-unique Header:
76  This software is developed by the MODIS Science Data Support
77  Team for the National Aeronautics and Space Administration,
78  Goddard Space Flight Center, under contract NAS5-32373.
79 
80 References and Credits
81  Based upon the ludcmp() function described in section 2.3 of "Numerical
82  Recipes in C", by Preus et. al., 1988.
83 
84 Design Notes
85  Changes from NR version by:
86  Use an IMSL return code to indicate errors, rather than calling nrerror.
87  Specialize for an array of size THREEDxTHREED, avoiding the need to
88  dynamically allocate vv.
89  Use 0-based indexing.
90  Use double precision variables instead of 'float', with a corresponding
91  change to the value for TINY.
92  Automatically adjusts singular arrays to be non-singular.
93 
94  Input arguments are not checked, because this is a static function that
95  will be only be called by routines in the same source code file, which
96  will be responsible for checking them before calling this function.
97 !END**************************************************************************
98 */
99  int row, col, k; /* loop counters. */
100  int rowmax; /* the index of the best row for a partial pivot */
101  double big, dum, sum, temp; /* intermediate results */
102  double vv[THREED]={0.0}; /* the implicit scaling of each row. */
103 
104  *d = 1.0; /* No interchanges yet */
105 
106  for(row=0; row<THREED; row++)
107  { /* To get implicit scaling information*/
108 
109  big = fabs(a[row][0]);
110  for(col=0; col<THREED; col++)
111  { /* find the largest of the absolute values of elements in a[row] */
112  temp = fabs(a[row][col]);
113  if(temp > big)
114  big = temp;
115  }
116 
117  if(big < TINY)
118  IMSL_error_code = IMSL_SINGULAR_MATRIX;
119  else
120  vv[row] = 1.0/big; /* Save the scaling */
121  }
122 
123  for(col=0; col<THREED; col++) /* Crout's method*/
124  {
125  for(row=0; row<col; row++) /* equation 2.1.13 except for i==j */
126  {
127  sum = a[row][col];
128  for(k=0; k<row; k++)
129  sum -= a[row][k]*a[k][col];
130  a[row][col] = sum;
131  }
132 
133  big = 0.0; /* Initialize for the search for the largest pivot. */
134  for(row=col; row<THREED; row++)
135  { /* This is i==j of equation 2.3.12 and i=j+1...N of equation 2.3.13 */
136  sum = a[row][col];
137  for(k=0; k<col; k++)
138  sum -= a[row][k]*a[k][col];
139  a[row][col] = sum;
140  dum = vv[row]*fabs(sum);
141  if(dum >= big)
142  { /* Figure of merit for the pivot is better than best so far. */
143  big = dum;
144  rowmax = row;
145  }
146  }
147 
148  if(col != rowmax)
149  { /* Need to interchange rows. */
150  for(k=0; k<THREED; k++)
151  {
152  temp = a[rowmax][k];
153  a[rowmax][k] = a[col][k];
154  a[col][k] = temp;
155  }
156  *d *= -1.0; /* And change the parity of d */
157  vv[rowmax] = vv[col]; /* Also interchange the scale factor. */
158  /* Not swapped?? */
159  }
160 
161  indx[col] = rowmax;
162  if(fabs(a[col][col]) < TINY)
163  {
164  /* Remove singularities and near-singularities */
165  a[col][col] = TINY;
166  IMSL_error_code = IMSL_SINGULAR_MATRIX;
167  }
168 
169  if(col != THREED-1) /* Now, finally, divide by the pivot element */
170  for(row=col+1; row<THREED; row++)
171  a[row][col] /= a[col][col];
172  }
173 
174 }
175 
176 static void lubksb3(
177  double a[THREED][THREED],
178  const int indx[THREED],
179  double b[THREED]
180 ){
181 /*******************************************************************************
182 !C
183 !Description:
184  Solves the set of 3 linear equations A*X = B. The 'a' given as input
185  contains the L/U decomposition of A, as performed by ludcmp().
186 
187 !Input Parameters:
188  a The elements of 'a' below the diagonal are the non-zero
189  off-diagonal elements of L; the elements of 'a' on and above
190  the diagonal are the non-zero elements of U, with the diagonal
191  elements of L being 0.0, such that A = L*U.
192  idnx The permutation vector returned by ludcmp()
193 
194 !Output Parameters:
195 
196 !Input/Output Parameters: (Remove this section if none exist)
197  b On input, contains the values of B. On output, contains the
198  values of the corresponding X vector.
199 
200 Return Parameters:
201  None
202 
203 Externally Defined:
204  THREED "imsl_d_lin_sol_gen.c"
205 
206 Called by:
207  imsl_d_lin_sol_gen "imsl_wrap.h"
208 
209 Routines Called:
210  None
211 
212 !Revision History:
213 See top of file.
214 
215 Requirements:
216 
217 !Team-unique Header:
218  This software is developed by the MODIS Science Data Support
219  Team for the National Aeronautics and Space Administration,
220  Goddard Space Flight Center, under contract NAS5-32373.
221 
222 References and Credits
223  Based upon the lubksb() function described in section 2.3 of "Numerical
224  Recipes in C", by Preuss et. al., 1988.
225 
226 Design Notes
227  Changes from NR version:
228  Uses 0-based indexing. Specialized for arrays of size THREED.
229 
230  Input arguments are not checked, because this is a static function that
231  will only be called by routines in the same source code file, which
232  will be responsible for checking them before calling this function.
233 !END**************************************************************************
234 */
235  double sum;
236  int row, col; /* loop indices */
237  int ip, ii=-1;
238 
239  for(row=0; row<THREED; row++)
240  {
241  ip = indx[row];
242  sum = b[ip];
243  b[ip] = b[row];
244  if(ii >= 0)
245  for(col=ii; col<row; col++)
246  sum -= a[row][col]*b[col];
247  else if(fabs(sum) > TINY)
248  ii = row;
249 
250  b[row] = sum;
251  }
252 
253  for(row = THREED-1; row>=0; row--)
254  {
255  sum = b[row];
256  for(col=row+1; col<THREED; col++)
257  sum -= a[row][col]*b[col];
258  b[row] = sum/a[row][row];
259  }
260 }
261 
262 double * IMSL_DECL imsl_d_lin_sol_gen(
263  int const dim,
264  double matrix[],
265  double not_used[],
266  ...
267 ){
268 /*******************************************************************************
269 !C
270 !Description:
271  Computes the inverse of the matrix provided.
272 
273 !Input Parameters:
274  dim The number of rows and columns in the matrix. The only
275  value permitted by this version is THREED.
276  matrix Array of size dim * dim containing the matrix.
277  not_used Not used, since IMSL_INVERSE_ONLY is mandatory.
278 
279 !Output Parameters:
280  ... Accepts a variable list of options using the C
281  <stdarg.h> interface. They come in sets, with
282  the first argument of each set being an int that
283  identifies the type of set. Multiple occurances
284  of each set type are permitted; the later
285  values replace the earlier ones. The following
286  sets of "optional" arguments are the only ones
287  supported by this version, and are both
288  mandatory:
289 
290  int IMLS_INVERSE_USER Indicates that the following argument is:
291  double inverse[] A user-allocated array of size dim*dim
292  for storing the inverse of matrix.
293 
294  int IMSL_INVERSE_ONLY Compute the inverse of 'matrix'. The argument
295  'not used' is ignored, and the return value is
296  NULL
297 
298 
299 !Input/Output Parameters: (Remove this section if none exist)
300 
301 Return Values:
302  NULL
303 
304 Externally Defined:
305  DBL_EPSILON <float.h>
306  IMSL_DECL "imsl_wrap.h"
307  IMSL_error_code "pseudo_imsl.h"
308  IMSL_OPTIONAL_ARG_NULL_1 "imsl_wrap.h"
309  IMSL_ILL_CONDITIONED "imsl_wrap.h"
310  IMSL_INVERSE "imsl_wrap.h"
311  IMSL_INVERSE_ONLY "imsl_wrap.h"
312  IMSL_INVERSE_USER "imsl_wrap.h"
313  IMSL_NEGATIVE_ORDER "imsl_wrap.h"
314  IMSL_UNEXPECTED_NULL_POINTER "imsl_wrap.h"
315  IMSL_UNKNOWN_OPTION "imsl_wrap.h"
316 
317 Called by:
318  GEO_cumulate_GRing
319 
320 Routines Called:
321  lubksb3 "imsl_d_lin_sol_gen.c"
322  ludcmp3 "imsl_d_lin_sol_gen.c"
323 
324 !Revision History:
325 See top of file.
326 
327 Requirements:
328  None
329 
330 !Team-unique Header:
331  This software is developed by the MODIS Science Data Support
332  Team for the National Aeronautics and Space Administration,
333  Goddard Space Flight Center, under contract NAS5-32373.
334 
335 References and Credits
336  Based upon the documented interface for the correspondingly named real
337  IMSL library function.
338 
339 Design Notes
340  Differs from the real IMSL function in that it supports only the
341  IMSL_INVERSE_USER and IMSL_INVERSE_ONLY options, and makes both of them
342  mandatory, and it only works for dim==THREED.
343 
344 !END**************************************************************************
345 */
346  va_list ap;
347  double col[THREED];
348  int indx[THREED];
349  double factor[THREED][THREED];
350  double *inverse=NULL;
351  int row, c, arg, inverse_only=0;
352  double d;
353  double biggest=0.0, biginv=0.0, temp;
354 
355  IMSL_error_code = (Imsl_code)0;
356 
357  /* Collect arguments. */
358  va_start(ap, not_used);
359  while(( arg=va_arg(ap, int) )) /* = rather than == is deliberate */
360  {
361  switch(arg)
362  {
363  case IMSL_INVERSE_USER:
364  inverse = va_arg(ap,double *); break;
365 
366  case IMSL_INVERSE_ONLY:
367  inverse_only = 1; break;
368 
369  default:
370  IMSL_error_code = IMSL_UNKNOWN_OPTION; break;
371  }
372  }
373  va_end(ap);
374 
375  if(IMSL_error_code)
376  return NULL;
377 
378  if(inverse == NULL)
379  {
380  IMSL_error_code = IMSL_OPTIONAL_ARG_NULL_1;
381  return NULL;
382  }
383 
384  if(inverse_only == 0)
385  {
386  IMSL_error_code = IMSL_UNKNOWN_OPTION;
387  return NULL;
388  }
389 
390  if(matrix == NULL)
391  {
392  IMSL_error_code = IMSL_UNEXPECTED_NULL_POINTER;
393  return NULL;
394  }
395 
396  if(dim <= 0)
397  {
398  IMSL_error_code = IMSL_NEGATIVE_ORDER; /* Misnamed message mnemonic. */
399  return NULL;
400  }
401 
402  if(dim != THREED)
403  {
404  IMSL_error_code = IMSL_INTEGER_OUT_OF_RANGE;
405  return NULL;
406  }
407 
408  memcpy(factor, matrix, sizeof(factor));
409 
410  ludcmp3(factor, indx, &d);
411 
412  for(row=0; row<THREED; row++)
413  {
414  for(c=0; c<THREED; c++) /* Create identity matrix row */
415  col[c] = (row==c) ? 1.0 : 0.0;
416 
417  lubksb3(factor, indx, col);
418 
419  for(c=0; c<THREED; c++)
420  {
421  inverse[c*THREED+row] = col[c];
422  temp = fabs(col[c]);
423  if(temp > biginv)
424  biginv = temp;
425  temp = fabs(matrix[row*THREED+c]);
426  if(temp > biggest)
427  biggest = temp;
428  }
429  }
430 
431  /* biggest*biginv is a rough estimate of the condition number of the
432  * matrix.
433  */
434  if(IMSL_error_code == 0 && biggest*DBL_EPSILON*biginv > 1.0)
435  IMSL_error_code = IMSL_ILL_CONDITIONED;
436 
437  return NULL;
438 }
439 
#define NULL
Definition: decode_rs.h:63
double *IMSL_DECL imsl_d_lin_sol_gen(int const dim, double matrix[], double not_used[],...)
float ** matrix(long nrl, long nrh, long ncl, long nch)
Definition: nrutil.c:60
Imsl_code IMSL_error_code
Definition: imsl_error.c:20
#define THREED
data_t b[NROOTS+1]
Definition: decode_rs.h:77
make_L3 README txt Compiling set environment variables for HDBLIB and HDFINC to the appropriate HDF4 lib and include directories make_L3_v1 c o make_L3 LIB lib a I LIB I $HDFINC L $HDFLIB lmfhdf ldf lz ljpeg lm lmalloc Running make_L3 takes input from standard so the SeaWIFS level files should be piped to the program via the command line as in to be allocated by the program to buffer the compositing The the better Ideally it should be to fit the entire global required because of the skewness of the map projection If the number of lines is too then the compositing process may be slow But if the number of lines is too big
Definition: README.txt:68
#define TINY
#define fabs(a)
Definition: misc.h:93
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
PGE01 indicating that PGE02 PGE01 V6 for and PGE01 V2 for MOD03 were used to produce the granule By convention adopted in all MODIS Terra PGE02 code versions are The fourth digit of the PGE02 version denotes the LUT version used to produce the granule The source of the metadata environment variable ProcessingCenter was changed from a QA LUT value to the Process Configuration A sign used in error in the second order term was changed to a
Definition: HISTORY.txt:424
int k
Definition: decode_rs.h:73