OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
imsl_d_spline_interp.c
Go to the documentation of this file.
1 #include <stddef.h>
2 #include <math.h>
3 #include <float.h>
4 #include <stdarg.h>
5 #include "imsl_wrap.h"
6 #include "pseudo_imsl.h"
7 #include "GEO_geo.h"
8 
9 /*
10 Revision History:
11 $Log: imsl_d_spline_interp.c,v $
12 Revision 6.1 2010/06/18 20:25:23 kuyper
13 Corrected declaration of a banslv() parameter that is a pointer to an array by
14  removing 'const'.
15 
16 Revision 4.3 2003/08/28 16:21:03 kuyper
17 Corrected prolog.
18 
19 Revision 4.2 2003/07/01 20:11:25 kuyper
20 Corrected off-by-one errors in bsplvb(), banfac(), and splint().
21 Corrected descriptive text.
22 Changed imsl_d_spline_interp() to allocate memory as soon as the numbers
23  controlling the amount of memory needed have been validate, and to return
24  a pointer to that memory even when error conditions occur.
25 Corrected location pointed at by pspline->coef.
26 
27 Revision 4.1 2003/05/22 19:57:00 kuyper
28 Reverse-engineered from documentation and testing.
29 
30 James Kuyper Jr. (kuyper@saicmodis.com)
31  */
32 
33 static void bsplvb(
34  const double t[],
35  int jhigh,
36  double x,
37  int left,
38  double biatx[]
39 )
40 
41 /*******************************************************************************
42 !C
43 !Description:
44  Calculates the value of all possibly nonzero b-splines at x of order
45  jhigh with knot sequence t.
46 
47 !Input Parameters:
48  t Knot sequence of length left+jhigh, assumed to be nondecreasing.
49  ASSUMPTION: t[left] < t[left+1]
50  DIVISION BY ZERO will result if t[left] == t[left+1]
51  jhigh The order of the b-splines whose values at x are to be returned.
52  WARNING: the restriction jhigh<=MAX_SPLINE_ORDER is imposed
53  arbitrarily by the declaration of deltal and deltar below, but
54  is NOWHERE CHECKED for.
55  x The point at which the b-splines are to be evaluated.
56  left An integer chosen (usually) so that
57  t[left] <= x < t[left+1]
58 
59 !Output Parameters:
60  biatx An array of length jhigh, with biatx[i] containing the value at
61  x of the polynomial of order jhigh which agrees with the
62  b-spline b[left-jhigh+i][jout](t) on the interval (t[left],
63  t[left+1]).
64 
65 Return Value:
66  None
67 
68 Externally Defined:
69  MAX_SPLINE_ORDER "pseudo_imsl.h"
70 
71 Called by:
72  splint()
73 
74 Routines Called:
75  None
76 
77 !Revision History:
78 See top of file.
79 
80 Requirements:
81  None
82 
83 !Team-unique Header:
84  This software is developed by the MODIS Science Data Support
85  Team for the National Aeronautics and Space Administration,
86  Goddard Space Flight Center, under contract NAS5-32373.
87 
88 References and Credits
89  This routine is a port to C of the Fortran program of the same name as
90  described by Carl de Boor in "A Practical Guide to Splines", 2001. The
91  original routine can be found in bsplvb.f, which is part of the pppack
92  package which can be downloaded from
93  <ftp://netlib.bell-labs.com/netlib/pppack.tar>
94 
95 Design Notes
96  The recurrence relation
97  x - t[i] t[i+j+1] - x
98  b[i][j+1](x) = -----------b[i][j+1](x) + ---------------b[i+1][j](x)
99  t[i+j]-t[i] t[i+j+1]-t[i+1]
100 
101  is used (repeatedly) to generate the (j+1)-vector b[left-j][j+1](x),
102  ...,b[left][j+1](x) from the j-vector b[left-j+1][j](x),...,
103  b[left][j](x), storing the new values in biatx over the old. The facts
104  that
105  b[i][0] == 1 if t[i] <= x < t[i+1]
106  and that
107  b[i][j](x) == 0 unless t[i] <= x < t[i+j]
108  are used. The particular organization of the calculations follows
109  algorithm (8) in chapter X of de Boor (2001).
110 
111  Unlike the original, this version does not support incremental
112  calculation of the spline values.
113 !END**************************************************************************
114 */
115 {
116  int j;
117  int i, jp1;
118  double saved, term;
119  double deltal[MAX_SPLINE_ORDER], deltar[MAX_SPLINE_ORDER];
120 
121  biatx[0] = 1.0;
122 
123  for(j=0; j < jhigh-1; j=jp1)
124  {
125  jp1 = j+1;
126  deltar[j] = t[left+jp1] - x;
127  deltal[j] = x - t[left-j];
128  saved = 0.0;
129 
130  for(i=0; i<=j; i++)
131  {
132  term = biatx[i]/(deltar[i] + deltal[j-i]);
133  biatx[i] = saved + deltar[i]*term;
134  saved = deltal[j-i]*term;
135  }
136 
137  biatx[jp1] = saved;
138  }
139 }
140 
141 
142 static void banfac(
143  double *w[/* nrow */],
144  int nrow,
145  int nband
146 )
147 
148 /*******************************************************************************
149 !C
150 !Description:
151  From * A Practical Guide to Splines * by C. de Boor
152  Returns in w the LU-factorization (without pivoting) of the banded
153  matrix 'a' of order nrow with (2*nband + 1) bands or diagonals stored
154  in the work array w.
155 
156 !Input Parameters:
157  nrow Number of rows of data, assumed to be positive.
158  nband Number of bands of a above and below the main diagonal
159 
160 !Output Parameters:
161  None
162 
163 !Input/Output Parameters:
164  w On input, contains nrow pointers to arrays containing the
165  interesting part of a banded matrix 'a', with the diagonals or
166  bands of 'a' stored in the columns of w, while rows of 'a'
167  correspond to rows of w. This is the storage mode used in
168  linpak and results in efficient innermost loops.
169  Explicitly, 'a' has nband bands below the diagonal
170  + 1 (main) diagonal
171  + nband bands above the diagonal
172  and thus, a[j][i+j] is in w[j][i+nband]
173  for i=-nband,...,nband-1 and j=0,...,nrow-1.
174  On output, contains the LU-factorization of 'a' into a unit
175  lower triangular matrix L and an upper triangular matrix U
176  (both banded) and stored in customary fashion over the
177  corresponding entries of a. This makes it possible to solve
178  any particular linear system a*x = b for x by calling
179 
180  banslv ( w, nrow, nband, b )
181 
182  with the solution x contained in b on return .
183 
184 Return Values:
185  N/A
186 
187 Externally Defined:
188  None
189 
190 Called by:
191  splint()
192 
193 Routines Called:
194  None
195 
196 !Revision History:
197 See top of file.
198 
199 Requirements:
200  None
201 
202 !Team-unique Header:
203  This software is developed by the MODIS Science Data Support
204  Team for the National Aeronautics and Space Administration,
205  Goddard Space Flight Center, under contract NAS5-32373.
206 
207 References and Credits:
208  This routine is a port to C of the Fortran program of the same name as
209  described by Carl de Boor in "A Practical Guide to Splines", 2001. The
210  original routine can be found in banfac.f, which is part of the pppack
211  package which can be downloaded from
212  <ftp://netlib.bell-labs.com/netlib/pppack.tar>
213 
214 Design Notes:
215  Gauss eliminitation WITHOUT pivoting is used. The routine is intended
216  for use with matrices 'a' which do not require row interchanges during
217  factorization, especially for the TOTALLY POSITIVE matrices which occur
218  in spline calculations. The routine should not be used for an arbitrary
219  banded matrix.
220 
221  This routine differs from the original in that it's specialized for a
222  banded matrix with the same number of bands above and below the
223  diagonal, and that nrow is positive.
224  The nroww parameter was dropped, because the C version of the code does
225  not need it for the reasons that the fortran version did.
226  imsl_d_spline_interp() performs validity tests on the inputs which are
227  sufficient to guarantee that the matrix will not be singular.
228  Therefore, singularity checks have been removed, and so has the status
229  argument, which was used only to report the results of those checks.
230  Finally, since we can't use C99 yet, the 'w' argument can't be handled
231  as a variable-length array, which would have been an exact match to the
232  way it's handled in the Fortran version.
233 
234  This routine assumes that 'w' and all the pointers in the array it
235  points at are valid, and that the integral arguments all correctly
236  describe the memory that that those pointers point at. Ensuring these
237  validity conditions is the responsibility of the calling function. This
238  routine is declared static, so as to ensure that it can only be called
239  by functions that ensure the validity of those assumptions.
240 !END**************************************************************************
241 */
242 {
243  int i, j, k, ipk, jmax, midmk;
244  int nrowm1=nrow-1;
245  double factor, pivot;
246 
247  if(nrowm1<1 || nband <1)
248  return;
249 
250  /* 'a' in not just a triangular matrix. Construct LU factorization. */
251  for(i=0; i<nrowm1; i++)
252  {
253  pivot = w[i][nband];
254  jmax = (nband < nrow-i-1) ? nband : nrow-i-1;
255  for(j=0; j<jmax; j++)
256  w[i][nband+j+1] /= pivot;
257 
258  for(k=0; k<jmax; k++)
259  {
260  ipk = i+k+1;
261  midmk = nband-k;
262  factor = w[ipk][midmk-1];
263  for(j=0; j<jmax; j++)
264  w[ipk][midmk+j] -= w[i][nband+j+1]*factor;
265  }
266  }
267 
268  return;
269 }
270 
271 
272 static void banslv(
273  double *w[/* nrow */],
274  int nrow,
275  int nband,
276  double b[/* nrow */]
277 )
278 
279 /*******************************************************************************
280 !C
281 !Description:
282  Companion function to banfac(). It returns the solution x of the
283  linear system a*x = b in place of b, given the LU-factorization for 'a'
284  in the workarray w.
285 
286 !Input Parameters:
287  w An array of nrow pointers to double precision arrays containing
288  the LU-factorization of a banded matrix 'a' of order nrow, as
289  constructed in banfac(). For details, see banfac.c
290  nrow The number of rows in w.
291  nband The number of bands above and below the main diagonal in 'a'.
292 
293 !Output Parameters:
294  None
295 
296 !Input/Output Parameters:
297  b Input: Right side of the system to be solved.
298  Output: Solution vector
299 
300 Return Parameters:
301  N/A
302 
303 Externally Defined:
304  None
305 
306 Called by:
307  splint()
308 
309 Routines Called:
310 
311 !Revision History:
312 See top of file
313 
314 Requirements:
315  None
316 
317 !Team-unique Header:
318  This software is developed by the MODIS Science Data Support
319  Team for the National Aeronautics and Space Administration,
320  Goddard Space Flight Center, under contract NAS5-32373.
321 
322 References and Credits
323  This routine is a port to C of the Fortran program of the same name as
324  described by Carl de Boor in "A Practical Guide to Splines", 2001. The
325  original routine can be found in banslv.f, which is part of the pppack
326  package which can be downloaded from
327  <ftp://netlib.bell-labs.com/netlib/pppack.tar>
328 
329 Design Notes
330  (With 'a'=L*U, as stored in w,) the unit lower triangular system
331  L(U*x) = b is solved for y = u*x, and y stored in b. Then the upper
332  triangular system u*x = y is solved for x. The calculations are
333  arranged so that the innermost loops stay within rows.
334 
335  This routine differs from the original in that it's designed for arrays
336  where the number of bands above and below the diagonal are equal. This
337  simplifies our testing, since that's the only kind that
338  imsl_d_spline_interp() will be passing to this routine.
339  The nroww parameter was dropped, because the C version of the code does
340  not need it for the purpose that the fortran version did.
341 
342  This function assumes that it's pointer arguments are valid pointers,
343  that it's numeric arguments correctly describe the arrays that the
344  pointers point at, and that w[0][nband] is not too close to 0.0. For
345  nband<=0, it assumes that w[i][0] is not too close to 0.0. Those
346  validity checks are the responsibility of the calling routine. This
347  function is declared 'static', to ensure that it can only be called
348  directly by routines which do ensure those requirements.
349 !END**************************************************************************
350 */
351 {
352  int i, j, jmax, nrowm1;
353 
354  if(nrow != 1)
355  {
356  nrowm1 = nrow-1;
357 
358  if(nband>0)
359  {
360  /* Forward pass. */
361  for(i=0; i<nrowm1; i++)
362  {
363  jmax = (nband<nrow-i-1)? nband : nrow-i-1;
364  for(j=1; j<=jmax; j++)
365  b[i+j] -= b[i]*w[i][nband+j];
366  }
367  }
368  else
369  {
370  for(i=0; i<nrow; i++)
371  b[i] /= w[i][0];
372 
373  return;
374  }
375 
376  /* Backward pass. */
377  for(i=nrow-1; i>0; i--)
378  {
379  b[i] /= w[i][nband];
380  jmax = (nband<i)? nband : i;
381  for(j=1; j<=jmax; j++)
382  b[i-j] -= b[i]*w[i][nband-j];
383  }
384  }
385 
386  b[0] /= w[0][nband];
387 
388 }
389 
390 
391 static Imsl_code splint (
392  const double tau[],
393  const double gtau[],
394  const double t[],
395  int n,
396  int k,
397  double *q[],
398  double bcoef[]
399 )
400 /*******************************************************************************
401 !C
402 !Description: Computes a spline interpolant.
403 
404 !Input Parameters:
405  tau Array of length n, containing data point abscissae
406  ASSUMPTION: tau is strictly increasing
407  gtau Corresponding array of length n, containing data point
408  ordinates.
409  t Knot sequence, of length n+k
410  n Number of data points, and dimension of the spline
411  space s(k,t)
412  k Order of the spline.
413 
414 !Output Parameters:
415  q Array of n pointers to double arrays of length 2*k-1,
416  containing the triangular factorization of the
417  coefficient matrix of the linear system for the
418  b-coefficients of the spline interpolant.
419  The b-coeffs for the interpolant of an additional data
420  set (tau[i], htau[i]), i=1,...,n with the same data
421  abscissae can be obtained without going through all of
422  the calculations in this routine, simply by loading
423  htau into bcoef and then executing the call
424  banslv(q, n, k-1, bcoef).
425  bcoef The b-coefficients of the interpolant, of length n.
426 
427 
428 Return Value:
429  0 Success
430  IMSL_KNOT_DATA_INTERLACING The data and the knots are not properly
431  interlaced
432 
433 Externally Defined:
434  IMSL_KNOT_DATA_INTERLACING "imsl_wrap.h"
435 
436 Called by:
437  imsl_d_spline_interp()
438 
439 Routines Called:
440  bsplvb imsl_d_spline_interp.c
441  banfac imsl_d_spline_interp.c
442  banslv imsl_d_spline_interp.c
443 
444 !Revision History:
445 See top of file
446 
447 Requirements:
448 
449 !Team-unique Header:
450  This software is developed by the MODIS Science Data Support
451  Team for the National Aeronautics and Space Administration,
452  Goddard Space Flight Center, under contract NAS5-32373.
453 
454 References and Credits
455  "A Practical Guide to Splines - Revised edition", Carl de Boor,
456  copyright 2001
457  <http://netlib.bell-labs.com/netlib/master/readme.htm>
458 
459 Design Notes:
460  The is routine is a port to C from the FORTRAN routine named splint()
461  described by de Boor (2001). That routine is provide in the splint.f
462  file which is part of the pppack package which can be downloaded from
463  the netlib ftp site listed above.
464 
465  This function's implementation differs from the netlib splint() by:
466  Using the return value to indicate failure.
467 
468  This routine performs almost no validity checks on its arguments.
469  Ensuring their validity is the responsibility of the calling routine.
470  Therefore, this routine is static, so it can only be called from within
471  the same file, making it easier to verify that calling routine has
472  lived up to its responsibilities.
473 !END**************************************************************************
474 */
475 
476 {
477  int i, ilp1mx, j, kpkm2, left;
478  double taui;
479 
480  kpkm2 = 2*(k-1);
481  left = k-1;
482 
483  for(i=0; i<n; i++)
484  for(j=0; j<=kpkm2; j++)
485  q[i][j] = 0.0;
486 
487  /* Fill in the banded matrix with B-spline values at tau. */
488  for(i=0; i<n; i++)
489  {
490  taui = tau[i];
491  ilp1mx = (i+k<n) ? i+k-1 : n-1;
492  left = (left>i) ? left : i;
493 
494  /* Find 'left' in the closed interval (i, ilp1mx-1) such that
495  * t[left] <= tau[i] < t[left+1]
496  * matrix is singular if this is not possible.
497  */
498  if(taui < t[left])
499  return IMSL_KNOT_DATA_INTERLACING;
500 
501  while(taui >= t[left+1] && left < ilp1mx)
502  left++;
503 
504  if(taui > t[left+1])
505  return IMSL_KNOT_DATA_INTERLACING;
506 
507  bsplvb(t, k, taui, left, bcoef);
508 
509  for(j=0; j<k; j++)
510  q[left-k+j+1][2*k-2+i-left-j] = bcoef[j];
511  }
512 
513  banfac(q, n, k-1);
514  memcpy(bcoef, gtau, n*sizeof(double));
515  banslv(q, n, k-1, bcoef);
516 
517  return (Imsl_code)0;
518 }
519 
520 
521 Imsl_d_spline * IMSL_DECL imsl_d_spline_interp (
522  int ndata,
523  double xdata[],
524  double fdata[],
525  ...
526 )
527 /*******************************************************************************
528 !C
529 !Description: Computes a spline interpolant.
530 
531 !Input Parameters:
532  ndata The number of data points.
533  xdata Array with ndata components containing the abscissas of
534  the interpolation problem. Unlike the real IMSL
535  function, this version requires that they be in
536  ascending order.
537  fdata Array with ndata components containing the ordinates of
538  the interpolation problem.
539  ... Accepts a variable list of options, using the C
540  <stdarg.h> interface. They come in sets, with the first
541  argument of each set being an int that identifies the
542  type of set. Multiple occurences of each set type are
543  permitted; the later values replace the earlier ones.
544  The sets of optional arguments permitted are:
545 
546  int IMSL_ORDER Indicates that the next variable argument is:
547  int order The order of the spline subspace. Defaults to 4.
548 
549  int IMSL_KNOTS Indicates that the next variable argument is:
550  const double
551  knots[] A list of ndata+order knots, provided by the user.
552 
553  int 0 Terminates the variable arguments list.
554 
555 !Output Parameters:
556  None
557 
558 Return Value:
559  A pointer to a dynamically allocated structure that represents the
560  spline interpolant. If an interpolant cannot be computed, then NULL is
561  returned. The structure should be deallocated by calling free() when
562  the caller is done with it.
563 
564 Externally Defined:
565  __STDC_VERSION__ set by compiler
566  DBL_MAX <float.h>
567  IMSL_DECL "imsl_wrap.h"
568  IMSL_DUPLICATE_XDATA_VALUES "imsl_wrap.h"
569  IMSL_error_code "pseudo_imsl.h"
570  IMSL_KNOT_MULTIPLICITY "imsl_wrap.h"
571  IMSL_KNOT_NOT_INCREASING "imsl_wrap.h"
572  IMSL_KNOTS "imsl_wrap.h"
573  IMSL_ORDER "imsl_wrap.h"
574  IMSL_OUT_OF_MEMORY "imsl_wrap.h"
575  IMSL_OUT_OF_MEMORY_2 "imsl_wrap.h"
576  IMSL_UNEXPECTED_NULL_POINTER "imsl_wrap.h"
577  IMSL_SPLINE_NEED_DATA_PTS "imsl_wrap.h"
578  IMSL_UNKNOWN_OPTION "imsl_wrap.h"
579  IMSL_XDATA_NOT_INCREASING "imsl_wrap.h"
580  IMSL_XDATA_TOO_LARGE "imsl_wrap.h"
581  IMSL_XDATA_TOO_SMALL "imsl_wrap.h"
582  MAX_IMPULSE_NUMBER "GEO_geo.h"
583  MAX_SPLINE_ORDER "pseudo_imsl.h"
584 
585 Called by:
586  GEO_prepare_mirr_data "GEO_input.h"
587 
588 Routines Called:
589  splint imsl_d_spline_interp.c
590 
591 !Revision History:
592 See top of file.
593 
594 Requirements:
595 
596 !Team-unique Header:
597  This software is developed by the MODIS Science Data Support
598  Team for the National Aeronautics and Space Administration,
599  Goddard Space Flight Center, under contract NAS5-32373.
600 
601 References and Credits
602  "IMSL C/Math/Library", copyright 1990-2001, Visual Numerics, Inc.
603 
604 Design Notes:
605  The interface is intended to mimic a subset of the capabilities of the
606  correspondingly named IMSL library function. That will allow us to
607  make the use of the actual IMSL library optional, without requiring a
608  multiple versions of the code that uses the function. The actual work
609  is done by the splint() routine
610 
611  This function's interface differs from that of the real
612  imsl_d_spline_interp in that:
613  1. The xdata are required to be already sorted.
614  2. No default value is provided for the knots. They must be provided by
615  the user.
616  3. ndata can't exceed MAX_IMPULSE_NUMBER, and order can't exceed
617  MAX_SPLINE_ORDER.
618  4. It doesn't try to de-reference null pointer arguments.
619  5. Knots that are in decreasing order for some reason cause memory
620  segment violations for the IMSL routine. That shouldn't happen here.
621  (it shouldn't happen there, either).
622 
623 !END**************************************************************************
624 */
625 
626 #if __STDC_VERSION__ < 199901L
627  /* This definition makes the struct hack work on most C90 compilers, but
628  * produces undefined behavior in C99.
629  */
630  #define HACK_LENGTH 1
631 #else
632  /* This definition makes the struct hack work on all conforming C99
633  * compilers, but will produce a syntax error in C90.
634  */
635  #define HACK_LENGTH
636 #endif
637 {
638  typedef struct{
639  Imsl_d_spline spline;
640  int order, num_coef, num_knots;
641  double *knots;
642  double *coef;
643  double hack[HACK_LENGTH];
644  } spline_wrap;
645  spline_wrap *pspline;
646 
647  va_list ap;
648  int order=4;
649  const double *knots=NULL;
650  double w[MAX_IMPULSE_NUMBER][2*MAX_SPLINE_ORDER-1];
651  double *q[MAX_IMPULSE_NUMBER];
652  double epsilon;
653  int i, arg;
654 
655  IMSL_error_code = (Imsl_code)0;
656 
657  va_start(ap, fdata);
658  while((arg=va_arg(ap, int))) /* = is deliberate, not == */
659  {
660  if(arg==IMSL_ORDER)
661  order = va_arg(ap, int);
662  else if(arg==IMSL_KNOTS)
663  knots = va_arg(ap, double*);
664  else
665  {
666  IMSL_error_code = IMSL_UNKNOWN_OPTION; /* undocumented */
667  break;
668  }
669  }
670  va_end(ap);
671 
672  /* Validity checks */
673 
674  if(IMSL_error_code)
675  return NULL;
676 
677  if(order<1 || order>MAX_SPLINE_ORDER)
678  {
679  /* The upper limit is specific to pseudo-IMSL . */
680  IMSL_error_code = IMSL_SPLINE_BAD_ORDER; /* undocumented. */
681  return NULL;
682  }
683 
684  if(ndata < order)
685  {
686  IMSL_error_code = IMSL_SPLINE_NEED_DATA_PTS; /* undocumented. */
687  return NULL;
688  }
689 
690  if(ndata > MAX_IMPULSE_NUMBER)
691  {
692  IMSL_error_code = IMSL_OUT_OF_MEMORY; /* specific to pseudo-IMSL */
693  return NULL;
694  }
695 
696  /* Note: the real IMSL function computes default values for the knots, if
697  * IMSL_KNOTS isn't specified by the caller. The fact that this version
698  * doesn't do so makes IMSL_KNOTS mandatory.
699  */
700 
701  if(xdata==NULL || fdata==NULL || knots==NULL)
702  {
703  /* The IMSL routine doesn't bother checking this. */
704  IMSL_error_code = IMSL_UNEXPECTED_NULL_POINTER;
705  return NULL;
706  }
707 
708  /* Set up the spline structure. */
709  /* The following technique is well known as the "struct hack". IMSL appears
710  * to be using it in imsl_d_spline_interp().
711  */
712  pspline = (spline_wrap*) malloc(
713  offsetof(spline_wrap,hack)+(2*ndata+order)*sizeof(double));
714  if(!pspline)
715  {
716  IMSL_error_code = IMSL_OUT_OF_MEMORY_2; /* undocumented. */
717  return NULL;
718  }
719 
720  pspline->spline.domain_dim = 1;
721  pspline->spline.target_dim = 1;
722  pspline->spline.order = &pspline->order;
723  pspline->spline.num_coef = &pspline->num_coef;
724  pspline->spline.num_knots = &pspline->num_knots;
725  pspline->spline.knots = &pspline->knots;
726  pspline->spline.coef = &pspline->coef;
727 
728  pspline->order = order;
729  pspline->num_coef = ndata;
730  pspline->num_knots = order+ndata;
731  pspline->knots = pspline->hack;
732 
733  /* The next line had debatable legality in C90, but it works correctly on
734  * every real compiler. It is fully legal in C99, so long as hack is
735  * declared as "double hack[];", a declaration that would have been illegal
736  * in C90.
737  */
738  pspline->coef = pspline->hack+ndata+order;
739  memcpy(pspline->hack, knots, (ndata+order)*sizeof(double));
740 
741  epsilon = (knots[ndata+order-1]-knots[0]) / pow(DBL_MAX,1.0/(double)order);
742 
743  /* Calculations farther down will evaluate expressions whose value might
744  * overflow, but which should always be smaller in magnitude than
745  * pow((knots[ndata+order-1]-knots[0])/denominator,(double)order) for some
746  * particular value of 'denominator'. The validity checks below that use
747  * 'epsilon' are intended to ensure that 'denominator' is never small
748  * enough to cause those expressions to overflow. The real IMSL routines
749  * both do the equivalent of setting epsilon=0.0, which is a little riskier.
750  */
751 
752  for(i=0; i<ndata-1; i++)
753  {
754  if(xdata[i+1] < xdata[i])
755  {
756  /* This doesn't come up for the IMSL function; it sorts them. */
757  IMSL_error_code = IMSL_XDATA_NOT_INCREASING;
758  return &pspline->spline;
759  }
760 
761  if(xdata[i+1] - xdata[i] < epsilon)
762  {
763  IMSL_error_code = IMSL_DUPLICATE_XDATA_VALUES;
764  return &pspline->spline;
765  }
766  }
767 
768  for(i=0; i<ndata+order-1; i++)
769  if(knots[i+1] < knots[i])
770  {
771  /* This error code mnemonic is misnamed, but it is the documented
772  * one.
773  */
774  IMSL_error_code = IMSL_KNOT_NOT_INCREASING;
775  return &pspline->spline;
776  }
777 
778  for(i=0; i<ndata; i++)
779  {
780  if(knots[i+order]-knots[i] <= epsilon)
781  {
782  IMSL_error_code = IMSL_KNOT_MULTIPLICITY;
783  return &pspline->spline;
784  }
785 
786  /* The INTERLACE checks in the main code, combined with the
787  * NOT_INCREASING checks above, are sufficient to cover the next two
788  * cases, so in principle they don't need to be done separately.
789  * However, the IMSL routine does the equivalent of these redundant
790  * checks, and therefore, so must this version.
791  */
792  if(xdata[i] > knots[ndata])
793  {
794  IMSL_error_code = IMSL_XDATA_TOO_LARGE;
795  return &pspline->spline;
796  }
797 
798  if(xdata[i] < knots[order-1])
799  {
800  IMSL_error_code = IMSL_XDATA_TOO_SMALL;
801  return &pspline->spline;
802  }
803  }
804 
805  for(i=0; i<ndata; i++)
806  q[i] = w[i];
807 
808  IMSL_error_code = splint(xdata, fdata, knots, ndata, order, q,
809  pspline->coef);
810 
811  return &pspline->spline;
812 }
813 
data_t q
Definition: decode_rs.h:74
data_t t[NROOTS+1]
Definition: decode_rs.h:77
int j
Definition: decode_rs.h:73
#define MAX_SPLINE_ORDER
Definition: pseudo_imsl.h:52
#define NULL
Definition: decode_rs.h:63
#define HACK_LENGTH
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
Imsl_code IMSL_error_code
Definition: imsl_error.c:20
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 already in place for MODIS TERRA was implemented for MODIS AQUA A time dependent LUT was added which gives coefficients for a detector specific crosstalk correction based on the aggregated Band radiances The Band scaled integers are adjusted by the Band correction term
Definition: HISTORY.txt:439
Imsl_d_spline *IMSL_DECL imsl_d_spline_interp(int ndata, double xdata[], double fdata[],...)
data_t b[NROOTS+1]
Definition: decode_rs.h:77
int32_t nband
#define MAX_IMPULSE_NUMBER
Definition: GEO_geo.h:91
subroutine splint(xa, ya, y2a, n, x, y)
#define DBL_MAX
Definition: make_L3_v1.1.c:60
int i
Definition: decode_rs.h:71
int k
Definition: decode_rs.h:73