views:

45

answers:

3

I'm trying to work with large numbers (~10^14), and I need to be able to store them and iterate over loops of that length. ie.

n=SOME_BIG_NUMBER
do i=n,1,-1

I've tried the usual star notation, kind=8 etc. but nothing seemed to work.

Then I checked the huge(i) functions, and the code:

    program inttest

print *,huge(1)
print *,huge(2)
print *,huge(4)
print *,huge(8)
print *,huge(16)
print *,huge(32)

end program inttest

produces the number 2147483647 in all cases. Why? I'm using gfortran (f95) on a 64-bit machine.

If I'm going to need a bignum library, which one do people suggest?

Thanks, Sam

+1  A: 

The gfortran versions that I use, 4.3, 4.4 and 4.5 on a Mac, support 8-byte integers. The best way to select a variable type in Fortran >= 90 is to use an intrinsic function to specify the precision that you need. Try:

integer, parameter :: LargeInt_K = selected_int_kind (18)
integer (kind=LargeInt_K) :: i, n

to obtain at least 18 decimal digits, which will typically be a 8-byte integer.

With gfortran 4.3, huge (1_LargeInt_K) outputs 9223372036854775807. When you wrote huge (1), etc., by default the constant was a default integer, here evidently 4-bytes since huge returned 2147483647. So sometimes you need to specify the precision of constants, not just variables -- more commonly this trips people up when they lose significant figures on a real constant, which defaults to single precision.

Also see http://stackoverflow.com/questions/3170239/fortran-integer4-vs-integer4-vs-integerkind4

Usually gfortran has the command name gfortran. Could f95 be a different compiler? Try "gfortran -v" and "f95 -v".

M. S. B.
Thanks. I didn't realise huge worked like that, but it's obvious now.I've just found out my main problem was not casting my literals, I'd write n=123456...9 (kind=blah).Writing n=12...9_long where long=selected_int_kind(13) works fine.
Gyppo
One of the gfortran compile-time warning options will notify you of constants that are too large. Try:-fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wsurprising -Waliasing -Wimplicit-interface -Wunused-parameter -fcheck=all -fbacktracefor gfortran 4.5. or -fbounds-check for earlier versions instead of -fcheck-all
M. S. B.
+1  A: 

You've misunderstood the precise definition of the HUGE function. HUGE(num) returns the largest number with the same kind and type as num. The value returned also has the same kind and type as num. Since all your input values are (default) integers HUGE, correctly, returns the largest default-size integer.

HUGE(num) does not return the largest integer with kind=num. Nor does HUGE(num) return the largest number representable in num bytes. While many compilers use integer(kind=4) and integer(kind=8) etc for 4- and 8-byte integers, this is not guaranteed by the language standard and cannot be relied upon to be portable.

@MSB's answer tells you how to do what you want, I'm just butting in with some clarification.

High Performance Mark
A: 

Summary: Consider looking at compiler options.

It's been a l-o-n-g time since I've done FORTRAN, and I don't remember using HUGE(), but I looked at this a little. My Intel Linux machine has gfortran 4.1.2. I found I had to compile with the -fdefault-integer-8 option turned on to make it work for 64 bit integers. Specifically, with this code:

      program inttest
      print *, huge(1)
      end program inttest

running

$ gfortran inttest.for

created an executable which printed:

2147483647

However, running:

$ gfortran -fdefault-integer-8 inttest.for

resulted in an executable which gave the output:

9223372036854775807

Also, when I declared a variable as integer*8 and compiled without the -fdefault-integer-8 option, I got an error. The code:

  program inttest2
  integer*8  test_int
  test_int = 9223372036854775807
  print *, test_int
  end program inttest2

running

$ gfortran inttest2.for

resulted in

In file inttest.for:4

  test_int = 9223372036854775807  
                               1 

Error: Integer too big for its kind at (1)

However, things worked fine when I compiled with the -fdefault-integer-8 option and I got an executable which printed

9223372036854775807

Maybe there are other gfortran options which would be useful, but I didn't investigate further.

Granted, this still doesn't get you 10^14, but it may help explain the results you saw.

GreenMatt
The option -fdefault-integer-8 sets the default integer to 8 bytes and is not necessary to be able to use 8 byte integers; they can be obtained via declarations. The error message "Error: Integer too big for its kind at (1)" is telling you that the constant 9223372036854775807 is too large for its kind. You don't need to make the default integer kind 8 bytes to solve that problem -- you can specify the type of the constant.
M. S. B.
@M. S. B.: Thanks for explanation. How do you specify the constant type?
GreenMatt
The type of a constant is specified with an underscore followed by a kind value: 9223372036854775807_KindValue. It is best to use the intrinsic selected_int_kind (for integers, or selected_real_kind for reals) to define a integer/parameter "variable" KindValue (see answer to this question) rather than relying on a specific numeric value such as 8, which can vary in meaning between compilers.
M. S. B.