Search code examples
fortrangfortranfortran90arbitrary-precisionfmzm

Display arbitrary length formatted string using IM_FORM in the Fortran FMZM multiple precision library


I'm looking at the documentation for FMZM here, and from section 8.(c), I understand that:

(c) Subroutine FM_FORM does similar formatting, but we supply a character string for
    the formatted result.  After declaring the strings at the top of the routine, as with
          CHARACTER(80) :: ST1,ST2
    the WRITE above could become
          CALL FM_FORM('F15.6',H,ST1)
          CALL FM_FORM('E15.7',T,ST2)
          WRITE (*,"(' Step size = ',A,'  tolerance = ',A)") TRIM(ST1),TRIM(ST2)
    FM_FORM must be used instead of FM_FORMAT when there are more than 200 characters
    in the formatted string.  These longer numbers usually need to be broken into several
    lines.

I need to use the IM_FORM function to display big integers longer than 200 characters. In my case, substituting IM_FORM for FM_FORM above.

Following this example, I see a declaration for:

character(200) :: str

and some clever formatting:

str = IM_format( 'i200', result )   !<----- convert BigInt to string
print *, n, trim( adjustl(str) )    !<----- print huge integers

This is great when I know my output is less than 200 characters long. However, as I'm working with an arbitrary precision library, there are good odds I may have numbers substantially larger.

So working form something like:

   character(2000)       :: str   
   res = mygetlargenumberfunction(n)
   call im_form('i2000', res, str)

How can I declare my character(?) :: str variable and my IM_FORM format such that I can accomodate potentially substantially larger output unknown at compile-time? Am I left to simply guess a very large number?

Update addressing comments

I'm addressing both the allocation and the format string in the context of the FMZM arbitrary precision library, which is how it is not related to the question it is flagged as a duplicate of.

Changing

   character(2000)       :: str

to

   character (len=:), allocatable :: str

all other things being equal, produces

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
...
Segmentation fault (core dumped)

So this suggestion appears incompatible with FMZM.

Using gfortran -std=f2008 myprogram.F90 and

GNU Fortran (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

Solution

  • From @francescalus's nudge, I solved the problem this way:

       ! 
       character (len=:), allocatable :: str
       character(len=1024) :: fmat
       !
       res = mygetlargenumberfunction(n)      ! call the function
       lenr = log10(TO_FM(res))+1             ! size the string
       allocate(character(len=lenr) :: str)   ! now allocate the string itself
       write (fmat, "(A5,I0)") "i", lenr      ! create the format string
       call im_form(fmat, res, str)           ! do the call
       print*, trim( adjustl(str))