Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Fortran Programming Language

Lower index bound confusion


I'm confused by the rules for lower array index bound. In some
situations the index bound is retained, in other it is "shifted" so that
the lower bound becomes 1.

By experiment I noticed that if A(:) and B(:) are array pointers then e.g.

ALLOCATE(B(10:20))
A => B
WRITE(*,*) LBOUND(A,1)

A => B(10:20)
WRITE(*,*) LBOUND(A,1)

... yields
10
1

Is this guaranteed by the standard or is it compiler-dependent? Also i
noticed for dummy variables the lower index bound is by default shifted
to 1, even for array pointer actual argument, unless the dummy variable
is a pointer array, then the lower bound is retained. At least on my
compiler.

Is there some golden rule or thought behind all this that I fail to see?

On May 25, 9:49 am, Kurt <nob@nowhere.org> wrote:

Yes, there is. On pointer assignment, the bounds of the pointer are
determined as if LBOUND and UBOUND were applied to the target.
Thus, pointer assignment to a whole array variable inherits its lower
bounds, whereas assigment to a subobject gets the bounds of the
subobject, and every subobject has the default lower bounds, i.e. 1.
You can find more here:
http://en.wikipedia.org/wiki/Fortran_language_features#Pointers_as_dy...
On 25 mei, 10:12, highegg <high@gmail.com> wrote:

Note that similar problems occur if you pass an array like B(10:20) to
a
subroutine:

subroutine mysub( b )
    real, dimension(:) :: b

    write(*,*) lbound(b)
end subroutine

The lbound in the subroutine is 1, regardless of the lbound of the
actual argument.

I can think of a rationale for this behaviour (not sure if that is
correct, though): in this way subroutines and functions do not need
to take care of non-default lower bounds, by far the most common
case. If you need a different lower bound, then you can pass it
as an explicit argument:

subroutine mysub2( b, lower )
    integer :: lower
    real, dimension(lower:) :: b

    write(*,*) lbound(b)
end subroutine

Regards,

Arjen

Ok, sounds like there is some rationality here after all.

Another thing I noticed is that I can "shift" an array pointer with a
simple function. Is there some kind of intrinsic that does this? If not
- why not? I would like to avoid implementing one such function for each
element type and for different array ranks ...

   FUNCTION SHIFT(X,I) RESULT(Z)
     INTEGER, POINTER    :: Z(:)
     INTEGER, INTENT(IN) :: I
     INTEGER, POINTER    :: X(:)

     Z => SET_LB(X,LBOUND(X,1)+I)

   END FUNCTION SHIFT

   FUNCTION SET_LB(Y,J) RESULT(Z)
     INTEGER, POINTER    :: Z(:)
     INTEGER, INTENT(IN) :: J
     INTEGER, TARGET     :: Y(J:)

     Z => Y

   END FUNCTION SET_LB

On May 25, 2:33 pm, Kurt <nob@nowhere.org> wrote:

Yes, some time ago I discovered this trick, too, and put
it to the Wikipedia article I hyperlinked above.
It seems the only F95 way to assign a pointer to a non-ALLOCATEd
target with custom bounds.

In F2003, you can directly specify lower bounds for the pointer:
Z(LBOUND(X,1)+I:) => X

I am missing the feature in F95, too, but there is a way, even
standard-conforming, although clumsy, so I can live with it.

Thanks for responding again. I agree, nice to see it's in F2003.

But do you know if it's standard conforming to ALLOCATE an array
pointer, shift the index range as above, and then DEALLOCATE the shifted
array?

It seems to work with my compiler ...

On May 25, 3:58 pm, Kurt <nob@nowhere.org> wrote:

I think so. The array object created by pointer allocation can be
deallocated through any pointer that points to the same (entire)
object.

The reason that you're confused is that you're concentrating on
what looks like a simple case and ignoring the related hard
cases.  Remember, subscripts in arrays don't have to be simple.

What should the lower bound for P be after something like
      P => ARRAY(12:2:-3)

12, 3, and 2 all look equally obvious (to me ;) ).

Similarly for a CALL, what should the lower bound be for
     CALL SUB( ARRAY(1:5) + ARRAY(6:2:-1) )
again, no obvious answer.

I think the standard consistently says that a whole array has
it's declared bounds.  Any expression or section of an array acts
as if the bounds were declared to be 1:extent.  That means that
ARRAY and ARRAY(:) have different bounds.  Maybe it would be possible
to treat those two cases the same way, but then what would people
want or expect for ARRAY(I:J:K)?  Should that be special cased when
I is equal to the lower declared bound, J to the declared upper
bound, and K to 1?   Or worse, ARRAY( VECTOR ) when VECTOR happens
to span the declared bounds in order.

The current rules, whole array OR not, for determining bounds is
sometimes counter-intuitive (at least until you get comfortable
with it) but it covers all of the cases in a regular way with no
strange edge cases.

Dick Hendrickson

Dick Hendrickson wrote:

(snip)

> I think the standard consistently says that a whole array has
> it's declared bounds.  Any expression or section of an array acts
> as if the bounds were declared to be 1:extent.  That means that
> ARRAY and ARRAY(:) have different bounds.  Maybe it would be possible
> to treat those two cases the same way, but then what would people
> want or expect for ARRAY(I:J:K)?  Should that be special cased when
> I is equal to the lower declared bound, J to the declared upper
> bound, and K to 1?   Or worse, ARRAY( VECTOR ) when VECTOR happens
> to span the declared bounds in order.

PL/I does consistently keep the lower bound to arrays, including
as subroutine arguments.  PL/I does not have the I:J:K form,
so that problem doesn't come up.  It does have *, for an
array cross section.  An expression like SUM(A(I,*) * B(*,J))
multiplies row I of A by column J of B and subs the result.
They must have the same lower and upper bound.

> The current rules, whole array OR not, for determining bounds is
> sometimes counter-intuitive (at least until you get comfortable
> with it) but it covers all of the cases in a regular way with no
> strange edge cases.

PL/I does more general cases using the DEFINED attribute.
Similar to EQUIVALENCE, a DEFINED array shares storage with another
array, but isn't required to map contiguous storage.

DCL (A(10,10), B(10) DEFINED A(1SUB,1SUB)) FLOAT(10);

B contains the diagonal elements of A.

-- glen

glen herrmannsfeldt wrote:

...

> PL/I does consistently keep the lower bound to arrays, including
> as subroutine arguments.  PL/I does not have the I:J:K form,
> so that problem doesn't come up.  It does have *, for an
> array cross section.  An expression like SUM(A(I,*) * B(*,J))
> multiplies row I of A by column J of B and subs the result.
> They must have the same lower and upper bound.

I'd forgot that PL/I had that.  But you have failed to mention
(except obliquely) another difference.  You say that A and
B must have the same lower and upper bound - but Fortran's
equivalent requires only that they be conformable (the same
rank and the same extent in each corresponding dimention).
In Fortran, the *bounds* can be completely different.

This rule about conformability means that the fact that expression
results and array sections have a lower bound of one (regardless
of the bounds of the operands) is less often significant - or even
noticed.  Without the rule of conformability, operating on
sections would be nearly implossible.

--
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."   --  C. A. R. Hoare

James Giles wrote:
> glen herrmannsfeldt wrote:
>>PL/I does consistently keep the lower bound to arrays, including
>>as subroutine arguments.  PL/I does not have the I:J:K form,
>>so that problem doesn't come up.  It does have *, for an
>>array cross section.  An expression like SUM(A(I,*) * B(*,J))
>>multiplies row I of A by column J of B and subs the result.
>>They must have the same lower and upper bound.
> I'd forgot that PL/I had that.  But you have failed to mention
> (except obliquely) another difference.  You say that A and
> B must have the same lower and upper bound - but Fortran's
> equivalent requires only that they be conformable (the same
> rank and the same extent in each corresponding dimention).
> In Fortran, the *bounds* can be completely different.

Previous posts mentioned how Fortran array sections work.
I did say that it seemed more consistent.  Yes, it doesn't
do all the cases that Fortran can do.

> This rule about conformability means that the fact that expression
> results and array sections have a lower bound of one (regardless
> of the bounds of the operands) is less often significant - or even
> noticed.  Without the rule of conformability, operating on
> sections would be nearly implossible.

I would expect in the most common cases that it would work.
In the general case, one can always use DO loops.  As someone
else pointed out, for more complex expressions DO loops are
probably faster, anyway.  PL/I is probably better at generating
temporary arrays than Fortran.

Another difference from Fortran is in mixed array/scalar expressions.

A=A*A(10);

The effects of a change to A(10) are applied to subsequent elements,
where Fortran specifically says that the effects is as if the whole
multiply is done before the assignment.  Maybe in this case Fortran
is more likely to generate a temporary array.

-- glen

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc