!------------------------------------------------------------------------
! P_LEVEL.GREG
! Procedure to define contour levels for multichannel image
! Needs true_scale values => any p_level call must come after a p_scale call
!------------------------------------------------------------------------
define real range expo mant tmin tmax
define integer nmin nmax
define character space_mode*6 p3*6
!
let p3 "&3"
if p3.ne." " then
  let space_mode 'p3' /upper
else
  let space_mode 'space_type' /upper
endif
!
if (spacing.lt.0).or.(space_mode.eq."USER") then
  return
endif
let tmin true_scale[1]
let tmax true_scale[2]
if (tmin.eq.tmax) then
   message e levels "&1 has no range: Max = Min = " 'tmin'
   return error
endif
!
if (space_mode.eq."NOISE") then
  define real noise
  let noise &1%noise
  if (noise.eq.0) then
    compute noise rms &1
  endif
  if spacing.eq.0 then
    let range = log10(tmax-tmin)-log10(noise)
    let expo = int(range+20.)-21
    let mant = range-expo-1
    if (mant.lt.0.10) then
      let true_spacing 0.5*10**expo
    else if (mant.lt.0.30) then
      let true_spacing 10**expo
    else if (mant.lt.0.70) then
      let true_spacing 2.*10**expo
    else
      let true_spacing = 5.*10**expo
    endif
    let true_spacing true_spacing*noise
  else
    let true_spacing spacing*noise
  endif
else
  if (spacing.eq.0) then
    let range = log10(tmax-tmin)
    let expo = int(range+20.)-21
    let mant = range-expo-1
    if (mant.lt.0.25) then
      let true_spacing 10**expo
    else if (mant.lt.0.60) then
      let true_spacing 2.*10**expo
    else if (mant.lt.0.90) then
      let true_spacing = 5.*10**expo
    else
      let true_spacing = 10**(expo+1)
    endif
  else
    let true_spacing = spacing
  endif
endif
!
! Trap unrealistic values. 16777216.0 is the maximum dynamic an IEEE single
! precision float can encode
if (abs(tmin/true_spacing).gt.16777216.0).or.(abs(tmax/true_spacing).gt.16777216.0) then
  message e levels -
    "Spacing" 'true_spacing' "is smaller than the image precision in the range" -
    'tmin' 'tmax'
  message e levels "=> Increase the SPACING variable value to" -
   'max(abs(tmin)/16777216.0,abs(tmax)/16777216.0)' "at least"
  return error
endif
!
! There should be no integer overflow here as long as the above test is performed.
let nmin nint(min(tmin,tmax)|true_spacing)
let nmax nint(max(tmin,tmax)|true_spacing)
!
if (nmin.eq.0.and.nmax.eq.0) then
  ! tmin=0 and tmax=0
  message w level "No level in range"
  greg2\levels true_spacing
else if (nmin.le.0.and.nmax.ge.0) then
  ! min<0 and max>0
  if (scale[1].ne.0.and.scale[2].ne.0) then
    ! Custom scale limits: start from min level and increase
    ! until max level is reached or levels are exhausted
    greg2\levels -
      true_spacing*nmin to -0.95*true_spacing by true_spacing -
      true_spacing to true_spacing*(nmax+0.05) by true_spacing
  else if (nmin.ge.-20) then
    ! Less than 20 negative levels: start from min level and
    ! increase until max level is reached or levels are exhausted
    greg2\levels -
      true_spacing*nmin to -0.95*true_spacing by true_spacing -
      true_spacing to true_spacing*(nmax+0.05) by true_spacing
  else if (nmax.le.20) then
    ! Less than 20 positive levels: start from max level and
    ! decrease until min level is reached or levels are exhausted
    greg2\levels -
      true_spacing*nmax to true_spacing*0.95 by -true_spacing -
      -true_spacing to true_spacing*(nmin-0.05) by -true_spacing
  else
    ! More than 20 negative and more than 20 positive levels:
    ! start from 20-th min level and increase until levels are
    ! exhausted
    greg2\levels -
      true_spacing*-20 to -0.95*true_spacing by true_spacing -
      true_spacing to true_spacing*(20+0.05) by true_spacing
  endif
else if (nmin.ge.0) then
  ! min>0
  let nmin max(nmin,1)
  greg2\levels true_spacing*nmin to true_spacing*(nmax+0.05) by true_spacing
else if (nmax.le.0) then
  ! max<0
  !  Old behavior:
  ! let nmin -max(-nmin,1)
  ! greg2\levels true_spacing*nmin to true_spacing*(nmax+0.05) by true_spacing
  !  New behavior:
  greg2\levels true_spacing*nmax to true_spacing*(nmin-0.05) by -true_spacing
endif
!
let level_min true_spacing*nmin
let level_max true_spacing*nmax
