*------------- Telecommunications & Signal Processing Lab --------------
*                          McGill University
*
*
* Module:
*     SUBROUTINE SCALE (FMIN, FMAX, AXLEN, FIRSTV, DELTAV)
*
*
* Purpose:
*     Determine a plotting scale
*
*
* Description:
*     This routine determines a starting value and an increment for an
*     axis suitable for plotting a range of data values.  The scale
*     increment corresponding to axis intervals is chosen to be of the
*     form 1, 2 or 5 times 10**N.  The lower limit of the axis is the
*     largest integer multiple of the axis increment greater than or
*     equal to the lower limit of the data range.
*
*     The scale increment is chosen to be the smallest value of the
*     form 1, 2 or 5 time a power of ten, which gives a range which
*     spans the data limits with an axis length less than or equal to
*     the given value.
*
*     To allow for imprecision in the data range limits, a small
*     compensation is made at the top and bottom ends of the data
*     range.  The lower limit is a multiple of the increment which is
*     less than or equal to the lower limit of the data range plus a
*     small value.  The upper end of the axis is required to be larger
*     than the upper limit of the data range less a small value.
*
*
* Parameters:
* R ->  FMIN   - Minimum data value.  The order of the parameters FMIN
*                and FMAX may be interchanged.
* R ->  FMAX   - Maximum data value.  If FMIN is equal to FMAX, the
*                range of the data is assumed to be 0 to FMAX (or 0 to
*                1 if FMAX is zero).
* R ->  AXLEN  - Length of the axis in intervals (at least two)
* R <-  FIRSTV - Lower limit of the axis.  FIRSTV is a multiple of
*                DELTAV less than or equal to FMIN.
* R <-  DELTAV - Number of data units per axis interval
*
*
* Author / revision:
*     P. Kabal
*     $Revision: 1.7 $  $Date: 1995/03/08 15:28:47 $
*
*
*-----------------------------------------------------------------------

      SUBROUTINE SCALE (FMIN, FMAX, AXLEN, FIRSTV, DELTAV)


      REAL EPS
      PARAMETER (EPS=1E-4)

      INTEGER J
      INTEGER IFLORX

      REAL FMIN,FMAX,AXLEN,FIRSTV,DELTAV
      REAL AMIN,AMAX,DEL,P,DV,FV
      REAL FLOORX

      REAL EVEN(5)
      DATA EVEN/1.,2.,5.,10.,20./


* Determine the minimum and maximum data values
      IF (FMAX.GT.FMIN) THEN
        AMAX=FMAX
        AMIN=FMIN

      ELSE
        AMIN=FMAX
        AMAX=FMIN
        IF (AMAX.EQ.AMIN) THEN

          IF (AMAX.GT.0.0) THEN
            AMIN=0.0
          ELSE IF (AMAX.LT.0.0) THEN
            AMAX=0.0
          ELSE
            AMAX=1.0
          END IF

        END IF

      END IF

* The requirements are
*   n*Del <= Amin < Amax <=  n*Del + a*Del                       (1)
* where a=AXLEN, Del=DELTAV, and n*Del=FIRSTV

* For the lower limit,
*   n*Del <= Amin < (n+1)*Del.
* Let b*Del = Amin - n*Del.  Then 0 <= b < 1.
* For the upper limit,
*   Amax - Amin <= Del*(a-b), or  Del >= (Amax-Amin)/(a-b).
*
* Both Del and b are unknown.  Let
*  Del'=(Amax-Amin)/a .
* This Del' will satisfy (1) if Amin is a multiple of Del' (i.e., b=0).
* For Amin a multiple of Del', n=Amin/Del'.  If Amin is not a multiple
* of Del', the axis must be shifted, decreasing n by one.  Now the
* limit inequality may not be satisfied.  If it is not satisfied,
*   (Amax-Amin)/a = Del' < (Amax-Amin)/(a-b) < (Amax-Amin)/(a-1).
* Consider another value Del, satisfying Del/Del' >= a/(a-1).  Then,
* Del >= (Amax-Amin)/(a-1).  This value of Del satisfies (1) for
* n=floor[Amin/Del].

* We are looking for nice values Del.  The nice values increase by at
* least a factor of two between adjacent values.  Assume a >= 2.  Then
* a "nice" Del which is at most twice as large as Del' will satisfy
* (1).

* The power of ten scale factor must also be determined.  Nominally
* this is determined as M = floor[log10 (Del)].  The value Del is
* unknown at this point.  However, Del >= Del'.  Find
*   M = floor [ log10(Del') ].
* Let P=10**M.  Del'=P*D', where 1 <= D' < 10.
* With the normalization, we are looking for a nice value D which
* satisfies (1) with Del=P*D.  This nice-valued D is at most twice as
* large as D'.  The search loop tests values of D equal to 1, 2, 5, 10,
* and 20.  This set of values values guarantees that there is a D which
* is at least twice D'.
*
* An ancient Fortran compiler had an inaccurate LOG10 function; it did
* not return an integer value for powers of 10.  To avoid problems near
* integer values of the log10 function, M is calculated as
*   M = floor[ log10 (Del') + e ], where e is a small positive value.
* With this value of M and P=10**M, the normalized value D' is in the
* range 10**(-e) <= D' < 10*10**(-e).  The nice values D equal to 1, 2,
* 5, 10, and 20 are still appropriate.

* Finally the test (1) is modified to allow for some imprecision in
* Amin and Amax,
*   n*Del <= Amin + e*Del  and  Amax - e*Del <=  n*Del + a*Del .

      DEL=(AMAX-AMIN)/AXLEN
      P=10.**IFLORX(LOG10(DEL)+EPS)

* Search for a scale interval (EVEN(J)) larger than DEL
      DO 300 J=1,5
        DV=P*EVEN(J)
        IF (DV.GE.DEL) THEN

* The starting value must be a multiple of DV
* Check that the axis spans the data
          FV=FLOORX(AMIN/DV+EPS)*DV
          IF (AMAX.LE.FV+(AXLEN+EPS)*DV) GO TO 400

        END IF

 300  CONTINUE
      CALL WARN('SCALE - Number of intervals too small')

 400  FIRSTV=FV
      DELTAV=DV


      RETURN

      END
