C----------------------------------------------------------------------C

C These two routines are designed to allow precision to be deliberately
C thrown away in an IEEE floating point compliant computing environment
C (such as Intel x87 or Apple SANE) in order to more closely model
C computations in less precise floating point systems.
C
C----------------------------------------------------------------------C
C Copyright 2001 Kevin G. Rhoads
C
C Use is licensed under many of the so-called "public" licenses, per
C choice of user: GNU GPL, GNU LGPL, Artistic License, or the Q License
C
C----------------------------------------------------------------------C
C It is the responsibility of the user of this code to ensure that the
C initialization routine is called FIRST! => call moyel_init()
C before using moyel.
C
C----------------------------------------------------------------------C
C The function moyel is designed to "trim" precision from IEEE 32 bit reals.
C If you need to trim doubles or extended reals, convert to single and
C use moyel or write your own.
C
C trimmed_real = moyel( untrimmed_real, how_much_to_trim )
C where how_much_to_trim is an integer
C valid ranges for trimming are 0 to 24 bits
C if (how_much_to_trim .lt. 0) it is treated as zero
C if (how_much_to_trim .gt. 24) it is treated as 24
C for IEEE 32 bit reals, 24 bits of triming will remove all mantissa bits
C of UNnormals and DEnormals, and will leave only the implicit 1 bit of
C normalized reals
C
C-----------------------------------------------------------------------

C
C Regarding Hexadecimal constants: the old (non-standard) Microsoft syntax
C is #XXXXXXXX while the newer (on it's way to becoming standard) syntax is
C Z"XXXXXXXX" or Z'XXXXXXXX' -- both are provided below, with the new syntax
C commented out. Also, the hexadecimal constants have been printed out as
C standard decimal integers and are provided in that form also. So if your
C Fortran compiler does not support Hex constants in any form, use the decimal
C ones (but I suggest the Hex ones be kept in as comment lines)
C
C----------------------------------------------------------------------real function moyel(arg,trim)
real arg,foo
integer bar,trim
equivalence (foo,bar)
integer masks(25)
common /moyeldat/masks
save /moyeldat/
C----C
C It is the responsibility of the user of this code to ensure that the
C initialization routine is called FIRST! But, just in case, we will
C do what we can to guard against garbage computations.
C
C
if ( masks(25).ne.Z"FEABCD98" ) then
C
if ( masks(25).ne.Z'FEABCD98' ) then
C
if ( masks(25).ne.-22295144 ) then
if ( masks(25).ne.#FEABCD98 ) then
call moyel_init()
endif
C
foo = arg
if (trim.le.0) then
C do nothing
elseif (trim.ge.24) then
bar = iand(bar,masks(24))
else

bar = iand(bar,masks(trim))
endif
moyel = foo
return
end
C----------------------------------------------------------------------subroutine moyel_init()
integer masks(25)
common /moyeldat/masks
save /moyeldat/
C----masks(1) = #FFFFFFFE
masks(2) = #FFFFFFFC
masks(3) = #FFFFFFF8
masks(4) = #FFFFFFF0
masks(5) = #FFFFFFE0
masks(6) = #FFFFFFC0
masks(7) = #FFFFFF80
masks(8) = #FFFFFF00
masks(9) = #FFFFFE00
masks(10) = #FFFFFC00
masks(11) = #FFFFF800
masks(12) = #FFFFF000
masks(13) = #FFFFE000
masks(14) = #FFFFC000
masks(15) = #FFFF8000
masks(16) = #FFFF0000
masks(17) = #FFFE0000
masks(18) = #FFFC0000
masks(19) = #FFF80000
masks(20) = #FFF00000
masks(21) = #FFE00000
masks(22) = #FFC00000
masks(23) = #FF800000
masks(24) = #FF000000
masks(25) = #FEABCD98

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

masks( 1)
masks( 2)
masks( 3)
masks( 4)
masks( 5)
masks( 6)
masks( 7)
masks( 8)
masks( 9)
masks(10)
masks(11)
masks(12)
masks(13)
masks(14)
masks(15)
masks(16)
masks(17)
masks(18)
masks(19)
masks(20)
masks(21)
masks(22)
masks(23)
masks(24)
masks(25)
masks(1)
masks(2)
masks(3)
masks(4)
masks(5)
masks(6)
masks(7)
masks(8)
masks(9)
masks(10)
masks(11)

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

-2
-4
-8
-16
-32
-64
-128
-256
-512
-1024
-2048
-4096
-8192
-16384
-32768
-65536
-131072
-262144
-524288
-1048576
-2097152
-4194304
-8388608
-16777216
-22295144
Z"FFFFFFFE"
Z"FFFFFFFC"
Z"FFFFFFF8"
Z"FFFFFFF0"
Z"FFFFFFE0"
Z"FFFFFFC0"
Z"FFFFFF80"
Z"FFFFFF00"
Z"FFFFFE00"
Z"FFFFFC00"
Z"FFFFF800"

C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C

masks(12)
masks(13)
masks(14)
masks(15)
masks(16)
masks(17)
masks(18)
masks(19)
masks(20)
masks(21)
masks(22)
masks(23)
masks(24)
masks(25)
masks(1)
masks(2)
masks(3)
masks(4)
masks(5)
masks(6)
masks(7)
masks(8)
masks(9)
masks(10)
masks(11)
masks(12)
masks(13)
masks(14)
masks(15)
masks(16)
masks(17)
masks(18)
masks(19)
masks(20)
masks(21)
masks(22)

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

Z"FFFFF000"
Z"FFFFE000"
Z"FFFFC000"
Z"FFFF8000"
Z"FFFF0000"
Z"FFFE0000"
Z"FFFC0000"
Z"FFF80000"
Z"FFF00000"
Z"FFE00000"
Z"FFC00000"
Z"FF800000"
Z"FF000000"
Z"FEABCD98"
Z'FFFFFFFE'
Z'FFFFFFFC'
Z'FFFFFFF8'
Z'FFFFFFF0'
Z'FFFFFFE0'
Z'FFFFFFC0'
Z'FFFFFF80'
Z'FFFFFF00'
Z'FFFFFE00'
Z'FFFFFC00'
Z'FFFFF800'
Z'FFFFF000'
Z'FFFFE000'
Z'FFFFC000'
Z'FFFF8000'
Z'FFFF0000'
Z'FFFE0000'
Z'FFFC0000'
Z'FFF80000'
Z'FFF00000'
Z'FFE00000'
Z'FFC00000'

C
C
C

masks(23) = Z'FF800000'
masks(24) = Z'FF000000'
masks(25) = Z'FEABCD98'
return
end