mirror of
https://git.planet-casio.com/Lephenixnoir/OpenLibm.git
synced 2025-01-01 06:23:39 +01:00
c977aa998f
Replace amos with slatec
236 lines
6.9 KiB
Fortran
236 lines
6.9 KiB
Fortran
*DECK DEFCMN
|
|
SUBROUTINE DEFCMN (NDATA, XDATA, YDATA, SDDATA, NORD, NBKPT,
|
|
+ BKPTIN, MDEIN, MDEOUT, COEFF, BF, XTEMP, PTEMP, BKPT, G, MDG,
|
|
+ W, MDW, LW)
|
|
C***BEGIN PROLOGUE DEFCMN
|
|
C***SUBSIDIARY
|
|
C***PURPOSE Subsidiary to DEFC
|
|
C***LIBRARY SLATEC
|
|
C***TYPE DOUBLE PRECISION (EFCMN-S, DEFCMN-D)
|
|
C***AUTHOR Hanson, R. J., (SNLA)
|
|
C***DESCRIPTION
|
|
C
|
|
C This is a companion subprogram to DEFC( ).
|
|
C This subprogram does weighted least squares fitting of data by
|
|
C B-spline curves.
|
|
C The documentation for DEFC( ) has complete usage instructions.
|
|
C
|
|
C***SEE ALSO DEFC
|
|
C***ROUTINES CALLED DBNDAC, DBNDSL, DCOPY, DFSPVN, DSCAL, DSORT, XERMSG
|
|
C***REVISION HISTORY (YYMMDD)
|
|
C 800801 DATE WRITTEN
|
|
C 890531 Changed all specific intrinsics to generic. (WRB)
|
|
C 890618 Completely restructured and extensively revised (WRB & RWC)
|
|
C 891214 Prologue converted to Version 4.0 format. (BAB)
|
|
C 900315 CALLs to XERROR changed to CALLs to XERMSG. (THJ)
|
|
C 900328 Added TYPE section. (WRB)
|
|
C 900510 Convert XERRWV calls to XERMSG calls. (RWC)
|
|
C 900604 DP version created from SP version. (RWC)
|
|
C***END PROLOGUE DEFCMN
|
|
INTEGER LW, MDEIN, MDEOUT, MDG, MDW, NBKPT, NDATA, NORD
|
|
DOUBLE PRECISION BF(NORD,*), BKPT(*), BKPTIN(*), COEFF(*),
|
|
* G(MDG,*), PTEMP(*), SDDATA(*), W(MDW,*), XDATA(*), XTEMP(*),
|
|
* YDATA(*)
|
|
C
|
|
EXTERNAL DBNDAC, DBNDSL, DCOPY, DFSPVN, DSCAL, DSORT, XERMSG
|
|
C
|
|
DOUBLE PRECISION DUMMY, RNORM, XMAX, XMIN, XVAL
|
|
INTEGER I, IDATA, ILEFT, INTSEQ, IP, IR, IROW, L, MT, N, NB,
|
|
* NORDM1, NORDP1, NP1
|
|
CHARACTER*8 XERN1, XERN2
|
|
C
|
|
C***FIRST EXECUTABLE STATEMENT DEFCMN
|
|
C
|
|
C Initialize variables and analyze input.
|
|
C
|
|
N = NBKPT - NORD
|
|
NP1 = N + 1
|
|
C
|
|
C Initially set all output coefficients to zero.
|
|
C
|
|
CALL DCOPY (N, 0.D0, 0, COEFF, 1)
|
|
MDEOUT = -1
|
|
IF (NORD.LT.1 .OR. NORD.GT.20) THEN
|
|
CALL XERMSG ('SLATEC', 'DEFCMN',
|
|
+ 'IN DEFC, THE ORDER OF THE B-SPLINE MUST BE 1 THRU 20.',
|
|
+ 3, 1)
|
|
RETURN
|
|
ENDIF
|
|
C
|
|
IF (NBKPT.LT.2*NORD) THEN
|
|
CALL XERMSG ('SLATEC', 'DEFCMN',
|
|
+ 'IN DEFC, THE NUMBER OF KNOTS MUST BE AT LEAST TWICE ' //
|
|
+ 'THE B-SPLINE ORDER.', 4, 1)
|
|
RETURN
|
|
ENDIF
|
|
C
|
|
IF (NDATA.LT.0) THEN
|
|
CALL XERMSG ('SLATEC', 'DEFCMN',
|
|
+ 'IN DEFC, THE NUMBER OF DATA POINTS MUST BE NONNEGATIVE.',
|
|
+ 5, 1)
|
|
RETURN
|
|
ENDIF
|
|
C
|
|
NB = (NBKPT-NORD+3)*(NORD+1) + (NBKPT+1)*(NORD+1) +
|
|
+ 2*MAX(NBKPT,NDATA) + NBKPT + NORD**2
|
|
IF (LW .LT. NB) THEN
|
|
WRITE (XERN1, '(I8)') NB
|
|
WRITE (XERN2, '(I8)') LW
|
|
CALL XERMSG ('SLATEC', 'DEFCMN',
|
|
* 'IN DEFC, INSUFFICIENT STORAGE FOR W(*). CHECK FORMULA ' //
|
|
* 'THAT READS LW.GE. ... . NEED = ' // XERN1 //
|
|
* ' GIVEN = ' // XERN2, 6, 1)
|
|
MDEOUT = -1
|
|
RETURN
|
|
ENDIF
|
|
C
|
|
IF (MDEIN.NE.1 .AND. MDEIN.NE.2) THEN
|
|
CALL XERMSG ('SLATEC', 'DEFCMN',
|
|
+ 'IN DEFC, INPUT VALUE OF MDEIN MUST BE 1-2.', 7, 1)
|
|
RETURN
|
|
ENDIF
|
|
C
|
|
C Sort the breakpoints.
|
|
C
|
|
CALL DCOPY (NBKPT, BKPTIN, 1, BKPT, 1)
|
|
CALL DSORT (BKPT, DUMMY, NBKPT, 1)
|
|
C
|
|
C Save interval containing knots.
|
|
C
|
|
XMIN = BKPT(NORD)
|
|
XMAX = BKPT(NP1)
|
|
NORDM1 = NORD - 1
|
|
NORDP1 = NORD + 1
|
|
C
|
|
C Process least squares equations.
|
|
C
|
|
C Sort data and an array of pointers.
|
|
C
|
|
CALL DCOPY (NDATA, XDATA, 1, XTEMP, 1)
|
|
DO 100 I = 1,NDATA
|
|
PTEMP(I) = I
|
|
100 CONTINUE
|
|
C
|
|
IF (NDATA.GT.0) THEN
|
|
CALL DSORT (XTEMP, PTEMP, NDATA, 2)
|
|
XMIN = MIN(XMIN,XTEMP(1))
|
|
XMAX = MAX(XMAX,XTEMP(NDATA))
|
|
ENDIF
|
|
C
|
|
C Fix breakpoint array if needed. This should only involve very
|
|
C minor differences with the input array of breakpoints.
|
|
C
|
|
DO 110 I = 1,NORD
|
|
BKPT(I) = MIN(BKPT(I),XMIN)
|
|
110 CONTINUE
|
|
C
|
|
DO 120 I = NP1,NBKPT
|
|
BKPT(I) = MAX(BKPT(I),XMAX)
|
|
120 CONTINUE
|
|
C
|
|
C Initialize parameters of banded matrix processor, DBNDAC( ).
|
|
C
|
|
MT = 0
|
|
IP = 1
|
|
IR = 1
|
|
ILEFT = NORD
|
|
INTSEQ = 1
|
|
DO 150 IDATA = 1,NDATA
|
|
C
|
|
C Sorted indices are in PTEMP(*).
|
|
C
|
|
L = PTEMP(IDATA)
|
|
XVAL = XDATA(L)
|
|
C
|
|
C When interval changes, process equations in the last block.
|
|
C
|
|
IF (XVAL.GE.BKPT(ILEFT+1)) THEN
|
|
CALL DBNDAC (G, MDG, NORD, IP, IR, MT, ILEFT-NORDM1)
|
|
MT = 0
|
|
C
|
|
C Move pointer up to have BKPT(ILEFT).LE.XVAL, ILEFT.LE.N.
|
|
C
|
|
DO 130 ILEFT = ILEFT,N
|
|
IF (XVAL.LT.BKPT(ILEFT+1)) GO TO 140
|
|
IF (MDEIN.EQ.2) THEN
|
|
C
|
|
C Data is being sequentially accumulated.
|
|
C Transfer previously accumulated rows from W(*,*) to
|
|
C G(*,*) and process them.
|
|
C
|
|
CALL DCOPY (NORDP1, W(INTSEQ,1), MDW, G(IR,1), MDG)
|
|
CALL DBNDAC (G, MDG, NORD, IP, IR, 1, INTSEQ)
|
|
INTSEQ = INTSEQ + 1
|
|
ENDIF
|
|
130 CONTINUE
|
|
ENDIF
|
|
C
|
|
C Obtain B-spline function value.
|
|
C
|
|
140 CALL DFSPVN (BKPT, NORD, 1, XVAL, ILEFT, BF)
|
|
C
|
|
C Move row into place.
|
|
C
|
|
IROW = IR + MT
|
|
MT = MT + 1
|
|
CALL DCOPY (NORD, BF, 1, G(IROW,1), MDG)
|
|
G(IROW,NORDP1) = YDATA(L)
|
|
C
|
|
C Scale data if uncertainty is nonzero.
|
|
C
|
|
IF (SDDATA(L).NE.0.D0) CALL DSCAL (NORDP1, 1.D0/SDDATA(L),
|
|
+ G(IROW,1), MDG)
|
|
C
|
|
C When staging work area is exhausted, process rows.
|
|
C
|
|
IF (IROW.EQ.MDG-1) THEN
|
|
CALL DBNDAC (G, MDG, NORD, IP, IR, MT, ILEFT-NORDM1)
|
|
MT = 0
|
|
ENDIF
|
|
150 CONTINUE
|
|
C
|
|
C Process last block of equations.
|
|
C
|
|
CALL DBNDAC (G, MDG, NORD, IP, IR, MT, ILEFT-NORDM1)
|
|
C
|
|
C Finish processing any previously accumulated rows from W(*,*)
|
|
C to G(*,*).
|
|
C
|
|
IF (MDEIN.EQ.2) THEN
|
|
DO 160 I = INTSEQ,NP1
|
|
CALL DCOPY (NORDP1, W(I,1), MDW, G(IR,1), MDG)
|
|
CALL DBNDAC (G, MDG, NORD, IP, IR, 1, MIN(N,I))
|
|
160 CONTINUE
|
|
ENDIF
|
|
C
|
|
C Last call to adjust block positioning.
|
|
C
|
|
CALL DCOPY (NORDP1, 0.D0, 0, G(IR,1), MDG)
|
|
CALL DBNDAC (G, MDG, NORD, IP, IR, 1, NP1)
|
|
C
|
|
C Transfer accumulated rows from G(*,*) to W(*,*) for
|
|
C possible later sequential accumulation.
|
|
C
|
|
DO 170 I = 1,NP1
|
|
CALL DCOPY (NORDP1, G(I,1), MDG, W(I,1), MDW)
|
|
170 CONTINUE
|
|
C
|
|
C Solve for coefficients when possible.
|
|
C
|
|
DO 180 I = 1,N
|
|
IF (G(I,1).EQ.0.D0) THEN
|
|
MDEOUT = 2
|
|
RETURN
|
|
ENDIF
|
|
180 CONTINUE
|
|
C
|
|
C All the diagonal terms in the accumulated triangular
|
|
C matrix are nonzero. The solution can be computed but
|
|
C it may be unsuitable for further use due to poor
|
|
C conditioning or the lack of constraints. No checking
|
|
C for either of these is done here.
|
|
C
|
|
CALL DBNDSL (1, G, MDG, NORD, IP, IR, COEFF, N, RNORM)
|
|
MDEOUT = 1
|
|
RETURN
|
|
END
|