2

I am trying to get a better understanding of the kind specification, so I wrote the following program.

program main
  implicit none

  real(kind = selected_real_kind(1)) :: a1
  real(kind = selected_real_kind(2)) :: a2

  print *, "Kind = ", kind(a1), "Range = ", range(a1)
  print *, "Kind = ", kind(a2), "Range = ", range(a2) 
end program main

The program runs great. However, my question is not about kind. My question is about using a do loop. I would like to make the program bigger, but I don't want to write out declaration and print statements over and over.

I don't think I have much choice on the declarations. I think I will have to write them out one at a time. Is that correct?

However, I do think there is a way to use a do loop for the print statements. Maybe something like this:

program main
  implicit none

  integer :: i
  real(kind = selected_real_kind(1)) :: a1
  real(kind = selected_real_kind(2)) :: a2

  do i = 1, 2
    print *, "Kind = ", kind(ai), "Range = ", range(ai)
  end do
end program main

Any suggestions?

David Hansen
  • 501
  • 4
  • 14

1 Answers1

2

You are going to come up against one problem with the loop approach: a kind selector when you use one must be a constant expression. I'm going to ignore the fact that you can't do dynamic variable selection, like construct ai as you have it to be a1 then a2: you'll find other questions about that.

A tempting approach for this is to use an array for the kind parameters. This is fine to an extent:

integer, parameter :: kinds(2) = [.., ..]
real(kinds(1)) :: a1
real(kinds(2)) :: a2

That is, you can use an element of a named constant (parameter) array as a kind parameter.

For those inquiry functions, as we're not selecting a1 and a2 in a loop, let's look at unnamed things (it's only the type and parameters that matter, after all).

do i=1, 2
  print *, "Kind = ", kinds(i)  ! KIND(ai) is just kinds(i)
end do

However, this works because of that relationship that kind(real(1,i)) is just i, when i is a valid kind selector.

In the more general looping case where it isn't just the kind numbers you want, but properties of the types with those kind parameters, you want to loopily construct an object of each kind. You'd like something with real(1,kinds(i)) and this is a problem. kinds(i) is not a constant expression, because i isn't, and so is not a valid kind selector.

Equally, you can't have a literal that looks like 1._kinds(i).

In summary, intuitively you're wanting to inquire about properties that are known at compile time, but using a loop to save on code. That loop though is inherently an executable thing.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • What if I made it more complicated. Something like: `print *, "a? =", a?, "kind=" kinds(i)` – David Hansen Jul 02 '15 at 22:09
  • Should that be an entirely new question? Should I/we edit the question? Sorry, I am still a bit new with Stack Overflow. Thanks for the patience. – David Hansen Jul 02 '15 at 22:11
  • For "how can I reference generically/dynamically `a1` and `a2` of different types/kinds?", yes that's probably a new question. Only because the answer is that you can't: if you could that's already an answer to this question as a method to what you want. Do search carefully though as there are questions on that already. (No link immediately, I'm afraid.). Well there's polymorphism but that doesn't actually help you in this case. – francescalus Jul 02 '15 at 22:23
  • You also have the option of things like in http://stackoverflow.com/q/25534202. I was tempted to suggest as duplication but I think there's some difference, or background missing. – francescalus Jul 02 '15 at 22:36