Silverfrost Forums

Welcome to our forums

OFFTOP: How this code works?

5 Aug 2008 6:38 (Edited: 7 Aug 2008 9:32) #3662

Saw the 'cool' footnote signature in fortran usersgroups forum where the author encripted his email address by using this trick (compile and run this tiny bit of text as free format text with switch /free or give it a filename and use extension f95

ftn95 filename.f95 /lgo )

write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, & 
6.0134700243160014d-154/),(/'x'/));end

How make it produce arbitrary text?

6 Aug 2008 11:40 #3665

Dan Conversion backwards and forward from text to numeric. One needs to have sufficient decimal precision in the real*8 constants to get back the exact text.

Ian

implicit real*8 (a-h,o-z)
character*32 line
real*8 data(4),d1,d2,d3,d4
parameter (d1=0.10273509947368046661d+201,  &
           d2=0.85408779798164891182d+195,  &
           d3=0.20628313781195820562d+167,  &
           d4=0.14508301358256921522d-46)

!convert a 32 character line of text to a four element real*8 array 
line='qwertyuiopasdfghjklzxcvbnm123456'
data=transfer(line,data,4)
print 1000,data
1000 format(e38.21)

!convert it back
print *,transfer(data,(/'x'/))

!from data statement
data(1) = d1
data(2) = d2
data(3) = d3
data(4) = d4
print *,transfer(data,(/'x'/))

!original example
write(*,*) transfer((/17.392111325966148d0+i*1.d-13,6.5794487871554595D-85, & 
6.0134700243160014d-154/),(/'x'/));end
7 Aug 2008 7:14 #3667

Something wrong is somewhere.... Here are first 4 lines this code produces

       0.102735099473680466610+201
       0.854087797981648911820+195
       0.206283137811958205620+167
       0.145083013582569215220E-46

Look at first three numbers carefully. What is this? What transfer function does and how it works?

7 Aug 2008 8:35 #3668

Dan,

It appears that the 'E' format only provides four characters for the exponent, and hence when three digits are required, the E is lost. I'm not sure what this means for input written to a file and subsequently read back.

The tranfer simply moves the data as bytes between the two representations, in much the same way that the EQUIVALENCE statement did, see the additional code. In the old days (when I was a lad) Fortran did not have character data and numeric data was used instead, simply being read or printed using an alpha-numeric or hollerith format when it was to be interpreted as text. By default FTN95 does not permit this old ragged method.

Regards

Ian

implicit real*8 (a-h,o-z)
character*32 line1,line2
real*8 data1(4),data2(4),d1,d2,d3,d4
parameter (d1=0.10273509947368046661d+201,  &
           d2=0.85408779798164891182d+195,  &
           d3=0.20628313781195820562d+167,  &
           d4=0.14508301358256921522d-46)

!convert a 32 character line of text to a four element real*8 array 
line1='qwertyuiopasdfghjklzxcvbnm123456'
data1=transfer(line1,data1,4)
print *,'Original text data converted to real*8'
print 1000,data1
1000 format(e38.21)
!convert it back
print *,'Converted back to text from real*8'
print *,transfer(data1,(/'x'/))

!from data statement
data1(1) = d1
data1(2) = d2
data1(3) = d3
data1(4) = d4
print *,'Text derived from data statements'
print *,transfer(data1,(/'x'/))

print *,'Conversion to real*8 using old fashioned equivalence method'
!using equivalence method
do i=1,4
  istart = (i-1)*8 + 1
  iend   = istart + 7
!convert eight byte lump from line1 to real*8 data
  call equivalent_r8(line1(istart:iend),data2(i))
  print 1000,data2(i)
! convert the real*8 data back to a text string in line2
  call equivalent_text8(data2(i),line2(istart:iend))
enddo
print *,'Conversion back to text using old fashioned equivalence method'
print *,line2


!original example
print *,'Original example'
write(*,*) transfer((/17.392111325966148d0+i*1.d-13,6.5794487871554595D-85, & 
6.0134700243160014d-154/),(/'x'/))
end

Subroutine equivalent_r8(text,real8)
!specify an 8byte text string and obtain the byte for byte translation to an 8 byte real
character*8 text, text_in_sub
real*8 real8, real8_in_sub
!use equivalence to specify an 8byte storage location to be common to a real*8 and text string 
equivalence (text_in_sub,real8_in_sub)
!put text into common area
text_in_sub = text
!take out real*8 from common area
real8       = real8_in_sub
end

Subroutine equivalent_text8(real8,text)
!specify an 8 byte real and obtain the byte for byte translation to an 8byte text string
character*8 text, text_in_sub
real*8 real8, real8_in_sub
!use equivalence to specify an 8byte storage location to be common to a real*8 and text string 
equivalence (text_in_sub,real8_in_sub)
!put real*8 into common area
real8_in_sub = real8
!take out text from common area
text         = text_in_sub
end
7 Aug 2008 9:59 #3671

Thanks, got it, tricky function, but useful

And meantime we seems revealed unbelievable FTN95 bug. Funny, nobody use real*8 numbers > 1.d+100 or <1.d-100 out here?

Interesting to check if it exists in FTN77 for DOS?! My colleague ones found missing factor 1.5 in his code after writing two books describing the results of the code 😮ops:

Please login to reply.