c
c     Copyright (c) 1999,2000, Compaq Computer Corporation
c
c     See the file "license.terms" for information on usage and redistribution
c     of this file, and for a DISCLAIMER OF ALL WARRANTIES.
c
c   Subroutines to provide autoscaling of data
c
      subroutine linear_autoscale(xmin, xmax, scale_type,
     1           new_xmin, new_xmax, exponent, tic_major,
     1           minor_tic_freq)
      implicit none
c
c     Given a data range (xmin,max), compute a new min and max
c     which is rounded to "nice" values for plotting on a linear scale.
c     Provide delta values for major and minor tic marks.
c
c     xmin - data range minimum (input)
c     xmax - data range maximum (input)
c     scale_type - Type of scaling (input)
c                  1 - Scientific notation
c                  2 - Engineering scientific notation
c     new_xmin - "nice" minimum for plotting, scaled by 10**exponent (output)
c     new_xmax - "nice" maximum for plotting, scaled by 10**exponent (output)
c     exponent -  scale magnification factor (power of ten)
c                 for plot range (output)
c                 Example: actual xmin = new_xmin * 10**exponent
c     tic_major - Major tic mark increment value,scaled by 10**exponent (output)
c     minor_tic_freq -
c                 Minor tic mark spacing is tic_major/minor_tic_freq (output)
c
      real xmin, xmax, new_xmin, new_xmax, tic_major
      integer scale_type, minor_tic_freq, exponent
c
c     The general scaling algorithm is given here, so it can be
c     modified to user tastes.
c
c       1) a) Separate (min,max) into a mantissa and integer exponent
c             using scientific notation (or engineering scientific notation,
c             where exponent is a multiple of three).

c             NOTE: scientific notation scaling is disabled when x is
c             in the range 0.001 <= x < 1000.0. This is done to give
c             more natural plot labels. Example: 0.1 rather than
c             1.0 * 10**-1; 10.0 rather than 1.0 * 10**1
c
c         b)  Scale mantissas so that the exponents are equal to the larger
c             of the two exponents.
c             Absolute value of mantissas are now bounded by (0.001,1000.0)
c
c       2) Compute new min and max range. Round mantissas depending
c          on difference between max and min, according to the following
c          table, where delta = (mantissa of xmax - mantissa of xmin)
c
c                delta > 200   ->  round to   100's digit; scale = 100
c          200 > delta > 20    ->  round to    10's digit; scale = 10
c           20 > delta > 2     ->  round to     1's digit; scale = 1
c            2 > delta > 0.2   ->  round to   0.1's digit; scale = 0.1
c          0.2 > delta > 0.02  ->  round to  0.01's digit; scale = 0.01
c         0.02 > delta > 0.001 ->  round to 0.001's digit; scale = 0.001
c
c          Minimum values are rounded down; maximum values are rounded up.
c
c       3) Compute major and minor tic increment
c
c          new_delta = (new_xmax - new_xmin)/scale
c          new_delta >= 5  ->  major tic at every scale interval,
c                              minor tic at every half scale interval
c          new_delta < 5   ->  major tic at every scale interval,
c                              minor tic at every 1/5 scale interval
c
      integer SCIENTIFIC, ENGINEERING
      parameter (SCIENTIFIC  = 1)
      parameter (ENGINEERING = 2)
c
      integer new_delta
      real scaled_xmin, scaled_xmax, old_delta, scale
      real round_down_whole, round_up_whole
      character*15 buf1,buf2
c
c     Convert to common exponent
      if( ABS(xmin) .gt. ABS(xmax) ) then
         if( scale_type .eq. ENGINEERING ) then
            call cvt_eng_not(xmin,scaled_xmin,exponent)
         else
            call cvt_sci_not(xmin,scaled_xmin,exponent)
         endif
         scaled_xmax = xmax*10.0**(-exponent)
      else
         if( scale_type .eq. ENGINEERING ) then
            call cvt_eng_not(xmax,scaled_xmax,exponent)
         else
            call cvt_sci_not(xmax,scaled_xmax,exponent)
         endif
         if( exponent .eq. 0 ) then
            scaled_xmin = xmin
         else
            scaled_xmin = xmin*10.0**(-exponent)
         endif
      endif
c
c     Compute scaling factor
      old_delta = scaled_xmax - scaled_xmin
      if( old_delta .ge. 200.0 ) then
         scale = 100.0
      else if( old_delta .ge. 20.0 ) then
         scale = 10.0
      else if( old_delta .ge. 2.0 ) then
         scale = 1.0
      else if( old_delta .ge. 0.2 ) then
         scale = 0.1
      else if( old_delta .ge. 0.02 ) then
         scale = 0.01
      else if( old_delta .ge. 0.002 ) then
         scale = 0.001
      else if( old_delta .ge. 0.0002 ) then
         scale = 0.0001
      else if( old_delta .ge. 0.00002 ) then
         scale = 0.00001
      else if( old_delta .ge. 0.000002 ) then
         scale = 0.000001
      else
         scale = 0.0000001
      endif
c
c     Round data
      new_xmin = scale*round_down_whole(scaled_xmin/scale)
      new_xmax = scale*round_up_whole(scaled_xmax/scale)
c
c     Compute tics
      tic_major = scale
c     Compute number of major tic intervals (use NINT to get nearest
c        integer).
      new_delta = NINT( (new_xmax - new_xmin)/scale )
      if( new_delta .gt. 5 ) then
c        There are too many major tics. Reduce them by two means:
c        1) If new_delta is even, we can halve the number of major tics
c        and not have to modify the min and max range.
c        2) Otherwise, increase min or max to make an even interval
         if( MOD(new_delta,2) .ne. 0 ) then
c           new_delta is odd. Modify range to make it divisible by two.
c           Change the min or max which is odd (make it even by
c           increasing the overall range)
            if( MOD(NINT(new_xmax/scale),2) .eq. 0 ) then
c              Decrease lower limit
               new_xmin = new_xmin - scale
            else
c              Increase upper limit
               new_xmax = new_xmax + scale
            endif
         endif
         tic_major = 2.0*tic_major
         minor_tic_freq = 4
      else
         minor_tic_freq = 5
      endif
c
      if( tic_major .lt. 1.0E-3 .and. scale_type .eq. 1 ) then
c        Decrement remote exponent to show more decimal places in mantissa
         do while( tic_major .lt. 1.0E-3 .and.
     1            MAX(ABS(10.0*new_xmin),ABS(10.0*new_xmax)) .lt. 1.0E3)
            exponent = exponent - 1
            new_xmin = new_xmin*10
            new_xmax = new_xmax*10
            tic_major = tic_major*10
         end do
      endif
c
      return
      end
c
      subroutine cvt_eng_not(x,scaled_x,exponent)
      implicit none
c
c     Convert value x into engineering notation.
c
c     x - Input real value
c     scaled_x, exponent - Output values such that x = scaled_x * 10**exponent
c        and exponent is a multiple of three. Exponent is 0 when
c        x is in the range 0.001 <= x < 1E3
c
      real x, scaled_x
      integer exponent
c
      real FUZZ
      parameter (FUZZ = 0.0001)
c
      integer itemp
c
      if( 0.001 .le. ABS(x)  .and. ABS(x) .lt. 1.0E3 ) then
         scaled_x = x
         exponent = 0
      else if ( x .eq. 0.0 ) then
         scaled_x = x
         exponent = 0
      else
c        Compute exponent
         itemp = INT(ALOG10(ABS(x)) + FUZZ)
c        Round to multiple of three
         exponent = itemp/3
         if( exponent .lt. 0 ) exponent = exponent - 1
         exponent = 3*exponent
         scaled_x = x/(10.0**exponent)
      endif
c
      return
      end
      subroutine cvt_sci_not(x,scaled_x,exponent)
      implicit none
c
c     Convert value x into scientific notation.
c
c     x - Input real value
c     scaled_x, exponent -
c        Output values such that x = scaled_x * 10**exponent
c        No conversion is performed when x is in the range 0.001 <= x < 1E3
c
      real x, scaled_x
      integer exponent
c
      real FUZZ
      parameter (FUZZ = 0.0001)
c
*      if( 0.001 .le. ABS(x)  .and. ABS(x) .lt. 1.0E3 ) then
      if( 0.01 .le. ABS(x)  .and. ABS(x) .lt. 1.0E3 ) then
         scaled_x = x
         exponent = 0
      else if ( x .eq. 0.0 ) then
         scaled_x = x
         exponent = 0
      else
c        Compute exponent
         exponent = INT(ALOG10(ABS(x)) + FUZZ)
         if( ABS(x) .lt. 1.0 ) exponent = exponent - 1
         scaled_x = x/(10.0**exponent)
      endif
c
      return
      end
