2

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
Mittenchops
  • 18,633
  • 33
  • 128
  • 246
  • Possible duplicate of [Allocatable character variables in Fortran](https://stackoverflow.com/questions/20908053/allocatable-character-variables-in-fortran). Specifically, check [this](https://stackoverflow.com/a/20908194/2938526) answer, as it shows the syntax for allocatable character variables and states that you don't even need to allocate it previous to the assignment, in a modern compiler. – Rodrigo Rodrigues Nov 19 '18 at 06:50
  • I think the requirement to specify a format string in the CALL FM_FORMAT('XXXXX', res, str) makes this different, right? – Mittenchops Nov 19 '18 at 15:32
  • You will likely still need to allocate the now-allocatable character variable before passing it as an argument. – francescalus Nov 19 '18 at 16:09
  • Thanks, @francescalus, but if I knew how long the string would be given the dynamic nature of the RESULT call, I would just specify that at compile. FMZM doesn't seem to provide me introspection of how to ask "how long would this big integer be if it were a string?" to pass both to the allocation step and the format string. – Mittenchops Nov 19 '18 at 16:18
  • 2
    You can determine at run time, rather than compile time, with the deferred length (allocatable) variable. Determine it, approximately, with base 10 log. – francescalus Nov 19 '18 at 16:51
  • Yep, that makes sense. Got it. – Mittenchops Nov 19 '18 at 17:14

1 Answers1

2

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))
Mittenchops
  • 18,633
  • 33
  • 128
  • 246